Merge pull request #474 from tannewt/mcu_reset
Introduce reset mechanics to microcontroller.
This commit is contained in:
commit
3c49f53eac
@ -123,6 +123,7 @@ CFLAGS_CORTEX_M0 = \
|
||||
-DI2S_CALLBACK_MODE=false \
|
||||
-DTC_ASYNC=true \
|
||||
-DUSB_DEVICE_LPM_SUPPORT \
|
||||
-DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \
|
||||
-DCIRCUITPY_CANARY_WORD=0xADAF00 \
|
||||
-DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \
|
||||
--param max-inline-insns-single=500
|
||||
@ -315,6 +316,7 @@ SRC_BINDINGS_ENUMS = \
|
||||
digitalio/Direction.c \
|
||||
digitalio/DriveMode.c \
|
||||
digitalio/Pull.c \
|
||||
microcontroller/RunMode.c \
|
||||
help.c \
|
||||
util.c
|
||||
|
||||
|
@ -11,7 +11,8 @@ MEMORY
|
||||
}
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
|
||||
_bootloader_dbl_tap = _estack;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -11,7 +11,8 @@ MEMORY
|
||||
}
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
|
||||
_bootloader_dbl_tap = _estack;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -10,7 +10,8 @@ MEMORY
|
||||
}
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
|
||||
_bootloader_dbl_tap = _estack;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -11,7 +11,8 @@ MEMORY
|
||||
}
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
|
||||
_bootloader_dbl_tap = _estack;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -12,6 +12,7 @@ MEMORY
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -12,6 +12,7 @@ MEMORY
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
@ -64,7 +64,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
|
||||
}
|
||||
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(
|
||||
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
|
||||
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
|
||||
self->output = false;
|
||||
|
||||
common_hal_digitalio_digitalinout_set_pull(self, pull);
|
||||
@ -72,7 +72,7 @@ void common_hal_digitalio_digitalinout_switch_to_input(
|
||||
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(
|
||||
digitalio_digitalinout_obj_t* self, bool value,
|
||||
enum digitalio_drive_mode_t drive_mode) {
|
||||
digitalio_drive_mode_t drive_mode) {
|
||||
struct port_config pin_conf;
|
||||
port_get_config_defaults(&pin_conf);
|
||||
|
||||
@ -88,7 +88,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
|
||||
common_hal_digitalio_digitalinout_set_value(self, value);
|
||||
}
|
||||
|
||||
enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
|
||||
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT;
|
||||
}
|
||||
@ -131,7 +131,7 @@ bool common_hal_digitalio_digitalinout_get_value(
|
||||
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(
|
||||
digitalio_digitalinout_obj_t* self,
|
||||
enum digitalio_drive_mode_t drive_mode) {
|
||||
digitalio_drive_mode_t drive_mode) {
|
||||
bool value = common_hal_digitalio_digitalinout_get_value(self);
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
// True is implemented differently between modes so reset the value to make
|
||||
@ -141,7 +141,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
|
||||
}
|
||||
}
|
||||
|
||||
enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
if (self->open_drain) {
|
||||
return DRIVE_MODE_OPEN_DRAIN;
|
||||
@ -151,7 +151,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
}
|
||||
|
||||
void common_hal_digitalio_digitalinout_set_pull(
|
||||
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
|
||||
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
|
||||
enum port_pin_pull asf_pull = PORT_PIN_PULL_NONE;
|
||||
switch (pull) {
|
||||
case PULL_UP:
|
||||
@ -172,7 +172,7 @@ void common_hal_digitalio_digitalinout_set_pull(
|
||||
port_pin_set_config(self->pin->pin, &pin_conf);
|
||||
}
|
||||
|
||||
enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
|
||||
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
uint32_t pin = self->pin->pin;
|
||||
PortGroup *const port_base = port_get_group_from_gpio_pin(pin);
|
||||
|
@ -26,10 +26,13 @@
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "reset.h"
|
||||
#include "samd21_pins.h"
|
||||
|
||||
#include "shared-bindings/nvm/ByteArray.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Processor.h"
|
||||
|
||||
void common_hal_mcu_delay_us(uint32_t delay) {
|
||||
@ -51,9 +54,33 @@ void common_hal_mcu_enable_interrupts(void) {
|
||||
cpu_irq_restore(irq_flags);
|
||||
}
|
||||
|
||||
extern uint32_t _ezero;
|
||||
extern uint32_t _srelocate;
|
||||
|
||||
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
// Set up the defaults.
|
||||
_bootloader_dbl_tap = DBL_TAP_MAGIC;
|
||||
_ezero = CIRCUITPY_CANARY_WORD;
|
||||
|
||||
if (runmode == RUNMODE_BOOTLOADER) {
|
||||
if (&_bootloader_dbl_tap < &_srelocate) {
|
||||
mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
|
||||
}
|
||||
// Pretend to be the first of the two reset presses needed to enter the
|
||||
// bootloader. That way one reset will end in the bootloader.
|
||||
_bootloader_dbl_tap = DBL_TAP_MAGIC;
|
||||
} else if (runmode == RUNMODE_SAFE_MODE) {
|
||||
_ezero = CIRCUITPY_SOFTWARE_SAFE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_mcu_reset(void) {
|
||||
reset();
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
.base = {
|
||||
.type = &mcu_processor_type,
|
||||
},
|
||||
@ -62,7 +89,7 @@ mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
// NVM is only available on Express boards for now.
|
||||
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
|
||||
// The singleton nvm.ByteArray object.
|
||||
nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
|
||||
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
|
||||
.base = {
|
||||
.type = &nvm_bytearray_type,
|
||||
},
|
||||
|
@ -84,6 +84,7 @@ typedef enum {
|
||||
BROWNOUT,
|
||||
HARD_CRASH,
|
||||
USER_SAFE_MODE,
|
||||
SOFTWARE_SAFE_MODE
|
||||
} safe_mode_t;
|
||||
|
||||
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
||||
@ -375,7 +376,10 @@ bool start_mp(safe_mode_t safe_mode) {
|
||||
mp_hal_stdout_tx_str(".\r\n");
|
||||
} else
|
||||
#endif
|
||||
if (safe_mode != NO_SAFE_MODE) {
|
||||
if (safe_mode == SOFTWARE_SAFE_MODE) {
|
||||
mp_hal_stdout_tx_str("\r\nYou requested starting in safe mode from your software.");
|
||||
mp_hal_stdout_tx_str(".\r\nTo exit, please reset the board.\r\n");
|
||||
} else if (safe_mode != NO_SAFE_MODE) {
|
||||
mp_hal_stdout_tx_str("\r\nYou are running in safe mode which means something really bad happened.\r\n");
|
||||
if (safe_mode == HARD_CRASH) {
|
||||
mp_hal_stdout_tx_str("Looks like our core CircuitPython code crashed hard. Whoops!\r\n");
|
||||
@ -524,10 +528,14 @@ safe_mode_t samd21_init(void) {
|
||||
REG_MTB_MASTER = 0x00000000 + 6;
|
||||
#endif
|
||||
|
||||
// CIRCUITPY_SOFTWARE_SAFE_MODE works just like the canary except if it
|
||||
// survives we enter safe mode with a friendlier message.
|
||||
bool software_safe_mode = _ezero == CIRCUITPY_SOFTWARE_SAFE_MODE;
|
||||
|
||||
// On power on start or external reset, set _ezero to the canary word. If it
|
||||
// gets killed, we boot in safe mod. _ezero is the boundary between statically
|
||||
// allocated memory including the fixed MicroPython heap and the stack. If either
|
||||
// misbehaves, the canary will not be in tact after soft reset.
|
||||
// gets killed, we boot in safe mode. _ezero is the boundary between statically
|
||||
// allocated memory including the fixed MicroPython heap and the stack. If
|
||||
// either misbehaves, the canary will not be intact after soft reset.
|
||||
#ifdef CIRCUITPY_CANARY_WORD
|
||||
if (PM->RCAUSE.bit.POR == 1 || PM->RCAUSE.bit.EXT == 1) {
|
||||
_ezero = CIRCUITPY_CANARY_WORD;
|
||||
@ -607,6 +615,10 @@ safe_mode_t samd21_init(void) {
|
||||
return USER_SAFE_MODE;
|
||||
}
|
||||
|
||||
if (software_safe_mode) {
|
||||
return SOFTWARE_SAFE_MODE;
|
||||
}
|
||||
|
||||
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
|
||||
// Upgrade the nvm flash to include one sector for eeprom emulation.
|
||||
struct nvm_fusebits fuses;
|
||||
|
@ -62,7 +62,7 @@ volatile bool reset_on_disconnect = false;
|
||||
|
||||
void usb_dtr_notify(uint8_t port, bool set) {
|
||||
mp_cdc_enabled = set;
|
||||
if (!set && reset_on_disconnect) {
|
||||
if (!set && reset_on_disconnect && _bootloader_dbl_tap != 0) {
|
||||
reset_to_bootloader();
|
||||
}
|
||||
}
|
||||
|
@ -29,12 +29,12 @@
|
||||
|
||||
#include "asf/sam0/utils/cmsis/samd21/include/samd21.h"
|
||||
|
||||
// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
|
||||
#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4))
|
||||
#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
|
||||
|
||||
void reset_to_bootloader(void) {
|
||||
void reset(void) {
|
||||
flash_flush();
|
||||
*DBL_TAP_PTR = DBL_TAP_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void reset_to_bootloader(void) {
|
||||
_bootloader_dbl_tap = DBL_TAP_MAGIC;
|
||||
reset();
|
||||
}
|
||||
|
@ -26,6 +26,12 @@
|
||||
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
|
||||
|
||||
// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
|
||||
#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
|
||||
|
||||
extern uint32_t _bootloader_dbl_tap;
|
||||
|
||||
void reset_to_bootloader(void);
|
||||
void reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
|
||||
|
@ -128,6 +128,7 @@ SRC_BINDINGS_ENUMS = \
|
||||
digitalio/Direction.c \
|
||||
digitalio/DriveMode.c \
|
||||
digitalio/Pull.c \
|
||||
microcontroller/RunMode.c \
|
||||
util.c
|
||||
|
||||
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
|
||||
|
@ -59,7 +59,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
|
||||
}
|
||||
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(
|
||||
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
|
||||
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
|
||||
self->output = false;
|
||||
|
||||
if (self->pin->gpio_number == 16) {
|
||||
@ -75,7 +75,7 @@ void common_hal_digitalio_digitalinout_switch_to_input(
|
||||
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(
|
||||
digitalio_digitalinout_obj_t* self, bool value,
|
||||
enum digitalio_drive_mode_t drive_mode) {
|
||||
digitalio_drive_mode_t drive_mode) {
|
||||
self->output = true;
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
if (self->pin->gpio_number == 16) {
|
||||
@ -89,7 +89,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
|
||||
common_hal_digitalio_digitalinout_set_value(self, value);
|
||||
}
|
||||
|
||||
enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
|
||||
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT;
|
||||
}
|
||||
@ -136,7 +136,7 @@ bool common_hal_digitalio_digitalinout_get_value(
|
||||
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(
|
||||
digitalio_digitalinout_obj_t* self,
|
||||
enum digitalio_drive_mode_t drive_mode) {
|
||||
digitalio_drive_mode_t drive_mode) {
|
||||
bool value = common_hal_digitalio_digitalinout_get_value(self);
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
// True is implemented differently between modes so reset the value to make
|
||||
@ -146,7 +146,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
|
||||
}
|
||||
}
|
||||
|
||||
enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
if (self->open_drain) {
|
||||
return DRIVE_MODE_OPEN_DRAIN;
|
||||
@ -156,7 +156,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||
}
|
||||
|
||||
void common_hal_digitalio_digitalinout_set_pull(
|
||||
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
|
||||
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
|
||||
if (pull == PULL_DOWN) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"ESP8266 does not support pull down."));
|
||||
@ -174,7 +174,7 @@ void common_hal_digitalio_digitalinout_set_pull(
|
||||
}
|
||||
}
|
||||
|
||||
enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
|
||||
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
|
||||
digitalio_digitalinout_obj_t* self) {
|
||||
if (self->pin->gpio_number < 16 &&
|
||||
(READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) {
|
||||
|
@ -24,9 +24,12 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/microcontroller/Processor.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/microcontroller/Processor.h"
|
||||
|
||||
@ -34,6 +37,7 @@
|
||||
#include "ets_alt_task.h"
|
||||
#include "etshal.h"
|
||||
#include "osapi.h"
|
||||
#include "user_interface.h"
|
||||
#include "xtirq.h"
|
||||
|
||||
#define ETS_LOOP_ITER_BIT (12)
|
||||
@ -54,9 +58,21 @@ void common_hal_mcu_enable_interrupts() {
|
||||
enable_irq(saved_interrupt_state & ~(1 << ETS_LOOP_ITER_BIT));
|
||||
}
|
||||
|
||||
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
if (runmode == RUNMODE_BOOTLOADER) {
|
||||
mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
|
||||
} else if (runmode == RUNMODE_SAFE_MODE) {
|
||||
mp_raise_ValueError("ESP8226 does not support safe mode.");
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_mcu_reset(void) {
|
||||
system_restart();
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, returned by microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
.base = {
|
||||
.type = &mcu_processor_type,
|
||||
},
|
||||
|
@ -124,7 +124,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
enum digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
if (args[ARG_drive_mode].u_rom_obj == &digitalio_drive_mode_open_drain_obj) {
|
||||
drive_mode = DRIVE_MODE_OPEN_DRAIN;
|
||||
}
|
||||
@ -161,7 +161,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
enum digitalio_pull_t pull = PULL_NONE;
|
||||
digitalio_pull_t pull = PULL_NONE;
|
||||
if (args[ARG_pull].u_rom_obj == &digitalio_pull_up_obj) {
|
||||
pull = PULL_UP;
|
||||
}else if (args[ARG_pull].u_rom_obj == &digitalio_pull_down_obj) {
|
||||
@ -191,7 +191,7 @@ extern const digitalio_digitalio_direction_obj_t digitalio_digitalio_direction_o
|
||||
STATIC mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) {
|
||||
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
|
||||
enum digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
|
||||
digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
|
||||
if (direction == DIRECTION_INPUT) {
|
||||
return (mp_obj_t)&digitalio_direction_input_obj;
|
||||
}
|
||||
@ -262,7 +262,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) {
|
||||
mp_raise_AttributeError("Drive mode not used when direction is input.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
|
||||
digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
|
||||
if (drive_mode == DRIVE_MODE_PUSH_PULL) {
|
||||
return (mp_obj_t)&digitalio_drive_mode_push_pull_obj;
|
||||
}
|
||||
@ -277,7 +277,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_o
|
||||
mp_raise_AttributeError("Drive mode not used when direction is input.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
if (drive_mode == &digitalio_drive_mode_open_drain_obj) {
|
||||
c_drive_mode = DRIVE_MODE_OPEN_DRAIN;
|
||||
}
|
||||
@ -307,7 +307,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) {
|
||||
mp_raise_AttributeError("Pull not used when direction is output.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
|
||||
digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
|
||||
if (pull == PULL_UP) {
|
||||
return (mp_obj_t)&digitalio_pull_up_obj;
|
||||
} else if (pull == PULL_DOWN) {
|
||||
@ -324,7 +324,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t p
|
||||
mp_raise_AttributeError("Pull not used when direction is output.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_pull_t pull = PULL_NONE;
|
||||
digitalio_pull_t pull = PULL_NONE;
|
||||
if (pull_obj == &digitalio_pull_up_obj) {
|
||||
pull = PULL_UP;
|
||||
} else if (pull_obj == &digitalio_pull_down_obj) {
|
||||
|
@ -43,14 +43,14 @@ typedef enum {
|
||||
digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin);
|
||||
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self);
|
||||
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, enum digitalio_drive_mode_t drive_mode);
|
||||
enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode);
|
||||
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_value(digitalio_digitalinout_obj_t* self, bool value);
|
||||
bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, enum digitalio_drive_mode_t drive_mode);
|
||||
enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
|
||||
enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode);
|
||||
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
|
||||
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H
|
||||
|
@ -29,10 +29,10 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_direction_t {
|
||||
typedef enum {
|
||||
DIRECTION_INPUT,
|
||||
DIRECTION_OUTPUT
|
||||
};
|
||||
} digitalio_direction_t;
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} digitalio_direction_obj_t;
|
||||
|
@ -29,10 +29,10 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_drive_mode_t {
|
||||
typedef enum {
|
||||
DRIVE_MODE_PUSH_PULL,
|
||||
DRIVE_MODE_OPEN_DRAIN
|
||||
};
|
||||
} digitalio_drive_mode_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
|
@ -29,11 +29,11 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_pull_t {
|
||||
typedef enum _digitalio_pull_t {
|
||||
PULL_NONE,
|
||||
PULL_UP,
|
||||
PULL_DOWN
|
||||
};
|
||||
} digitalio_pull_t;
|
||||
|
||||
const mp_obj_type_t digitalio_pull_type;
|
||||
|
||||
|
90
shared-bindings/microcontroller/RunMode.c
Normal file
90
shared-bindings/microcontroller/RunMode.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 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 "shared-bindings/microcontroller/RunMode.h"
|
||||
|
||||
//| .. currentmodule:: microcontroller
|
||||
//|
|
||||
//| :class:`RunMode` -- run state of the microcontroller
|
||||
//| =============================================================
|
||||
//|
|
||||
//| .. class:: microcontroller.RunMode
|
||||
//|
|
||||
//| Enum-like class to define the run mode of the microcontroller and
|
||||
//| CircuitPython.
|
||||
//|
|
||||
//| .. data:: NORMAL
|
||||
//|
|
||||
//| Run CircuitPython as normal.
|
||||
//|
|
||||
//| .. data:: SAFE_MODE
|
||||
//|
|
||||
//| Run CircuitPython in safe mode. User code will not be run and the
|
||||
//| file system will be writeable over USB.
|
||||
//|
|
||||
//| .. data:: BOOTLOADER
|
||||
//|
|
||||
//| Run the bootloader.
|
||||
//|
|
||||
const mp_obj_type_t mcu_runmode_type;
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_normal_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_safe_mode_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_bootloader_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t mcu_runmode_locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_PTR(&mcu_runmode_normal_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_SAFE_MODE), MP_ROM_PTR(&mcu_runmode_safe_mode_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_BOOTLOADER), MP_ROM_PTR(&mcu_runmode_bootloader_obj)},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mcu_runmode_locals_dict, mcu_runmode_locals_dict_table);
|
||||
|
||||
STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
qstr runmode = MP_QSTR_NORMAL;
|
||||
if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) {
|
||||
runmode = MP_QSTR_SAFE_MODE;
|
||||
} else if (MP_OBJ_TO_PTR(self_in) ==
|
||||
MP_ROM_PTR(&mcu_runmode_bootloader_obj)) {
|
||||
runmode = MP_QSTR_SAFE_MODE;
|
||||
}
|
||||
mp_printf(print, "%q.%q.%q", MP_QSTR_microcontroller, MP_QSTR_RunMode,
|
||||
runmode);
|
||||
}
|
||||
|
||||
const mp_obj_type_t mcu_runmode_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_RunMode,
|
||||
.print = mcu_runmode_print,
|
||||
.locals_dict = (mp_obj_t)&mcu_runmode_locals_dict,
|
||||
};
|
47
shared-bindings/microcontroller/RunMode.h
Normal file
47
shared-bindings/microcontroller/RunMode.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef enum {
|
||||
RUNMODE_NORMAL,
|
||||
RUNMODE_SAFE_MODE,
|
||||
RUNMODE_BOOTLOADER
|
||||
} mcu_runmode_t;
|
||||
|
||||
const mp_obj_type_t mcu_runmode_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} mcu_runmode_obj_t;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_normal_obj;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_safe_mode_obj;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_bootloader_obj;
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
@ -102,6 +102,47 @@ STATIC mp_obj_t mcu_enable_interrupts(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts);
|
||||
|
||||
//| .. method:: on_next_reset(run_mode)
|
||||
//|
|
||||
//| Configure the run mode used the next time the microcontroller is reset but
|
||||
//| not powered down.
|
||||
//|
|
||||
//| :param ~microcontroller.RunMode run_mode: The next run mode
|
||||
//|
|
||||
STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) {
|
||||
mcu_runmode_t run_mode;
|
||||
if (run_mode_obj == &mcu_runmode_normal_obj) {
|
||||
run_mode = RUNMODE_NORMAL;
|
||||
} else if (run_mode_obj == &mcu_runmode_safe_mode_obj) {
|
||||
run_mode = RUNMODE_SAFE_MODE;
|
||||
} else if (run_mode_obj == &mcu_runmode_bootloader_obj) {
|
||||
run_mode = RUNMODE_BOOTLOADER;
|
||||
} else {
|
||||
mp_raise_ValueError("Invalid run mode.");
|
||||
}
|
||||
|
||||
common_hal_mcu_on_next_reset(run_mode);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset);
|
||||
|
||||
//| .. method:: reset()
|
||||
//|
|
||||
//| Reset the microcontroller. After reset, the microcontroller will enter the
|
||||
//| run mode last set by `one_next_reset`.
|
||||
//|
|
||||
//| .. warning:: This may result in file system corruption when connected to a
|
||||
//| host computer. Be very careful when calling this! Make sure the device
|
||||
//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux.
|
||||
//|
|
||||
STATIC mp_obj_t mcu_reset(void) {
|
||||
common_hal_mcu_reset();
|
||||
// We won't actually get here because we're resetting.
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
|
||||
|
||||
//| .. attribute:: nvm
|
||||
//|
|
||||
//| Available non-volatile memory.
|
||||
@ -128,11 +169,14 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_on_next_reset), MP_ROM_PTR(&mcu_on_next_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mcu_reset_obj) },
|
||||
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
|
||||
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) },
|
||||
#else
|
||||
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Processor), MP_ROM_PTR(&mcu_processor_type) },
|
||||
|
@ -33,11 +33,16 @@
|
||||
|
||||
#include "common-hal/microcontroller/Processor.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/RunMode.h"
|
||||
|
||||
extern void common_hal_mcu_delay_us(uint32_t);
|
||||
|
||||
extern void common_hal_mcu_disable_interrupts(void);
|
||||
extern void common_hal_mcu_enable_interrupts(void);
|
||||
|
||||
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
|
||||
extern void common_hal_mcu_reset(void);
|
||||
|
||||
extern const mp_obj_dict_t mcu_pin_globals;
|
||||
|
||||
extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
|
||||
|
Loading…
Reference in New Issue
Block a user