Skip to content

Commit 3c49f53

Browse files
authored
Merge pull request adafruit#474 from tannewt/mcu_reset
Introduce reset mechanics to microcontroller.
2 parents 78db6c3 + a91e1cb commit 3c49f53

25 files changed

+308
-52
lines changed

atmel-samd/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ CFLAGS_CORTEX_M0 = \
123123
-DI2S_CALLBACK_MODE=false \
124124
-DTC_ASYNC=true \
125125
-DUSB_DEVICE_LPM_SUPPORT \
126+
-DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \
126127
-DCIRCUITPY_CANARY_WORD=0xADAF00 \
127128
-DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \
128129
--param max-inline-insns-single=500
@@ -315,6 +316,7 @@ SRC_BINDINGS_ENUMS = \
315316
digitalio/Direction.c \
316317
digitalio/DriveMode.c \
317318
digitalio/Pull.c \
319+
microcontroller/RunMode.c \
318320
help.c \
319321
util.c
320322

atmel-samd/boards/samd21x18-bootloader-crystalless.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ MEMORY
1111
}
1212

1313
/* top end of the stack */
14-
_estack = ORIGIN(RAM) + LENGTH(RAM);
14+
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
15+
_bootloader_dbl_tap = _estack;
1516

1617
/* define output sections */
1718
SECTIONS

atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ MEMORY
1111
}
1212

1313
/* top end of the stack */
14-
_estack = ORIGIN(RAM) + LENGTH(RAM);
14+
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
15+
_bootloader_dbl_tap = _estack;
1516

1617
/* define output sections */
1718
SECTIONS

atmel-samd/boards/samd21x18-bootloader-external-flash.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ MEMORY
1010
}
1111

1212
/* top end of the stack */
13-
_estack = ORIGIN(RAM) + LENGTH(RAM);
13+
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
14+
_bootloader_dbl_tap = _estack;
1415

1516
/* define output sections */
1617
SECTIONS

atmel-samd/boards/samd21x18-bootloader.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ MEMORY
1111
}
1212

1313
/* top end of the stack */
14-
_estack = ORIGIN(RAM) + LENGTH(RAM);
14+
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
15+
_bootloader_dbl_tap = _estack;
1516

1617
/* define output sections */
1718
SECTIONS

atmel-samd/boards/samd21x18-external-flash.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ MEMORY
1212

1313
/* top end of the stack */
1414
_estack = ORIGIN(RAM) + LENGTH(RAM);
15+
_bootloader_dbl_tap = 0;
1516

1617
/* define output sections */
1718
SECTIONS

atmel-samd/boards/samd21x18.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ MEMORY
1212

1313
/* top end of the stack */
1414
_estack = ORIGIN(RAM) + LENGTH(RAM);
15+
_bootloader_dbl_tap = 0;
1516

1617
/* define output sections */
1718
SECTIONS

atmel-samd/common-hal/digitalio/DigitalInOut.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
6464
}
6565

6666
void common_hal_digitalio_digitalinout_switch_to_input(
67-
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
67+
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
6868
self->output = false;
6969

7070
common_hal_digitalio_digitalinout_set_pull(self, pull);
7171
}
7272

7373
void common_hal_digitalio_digitalinout_switch_to_output(
7474
digitalio_digitalinout_obj_t* self, bool value,
75-
enum digitalio_drive_mode_t drive_mode) {
75+
digitalio_drive_mode_t drive_mode) {
7676
struct port_config pin_conf;
7777
port_get_config_defaults(&pin_conf);
7878

@@ -88,7 +88,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
8888
common_hal_digitalio_digitalinout_set_value(self, value);
8989
}
9090

91-
enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
91+
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
9292
digitalio_digitalinout_obj_t* self) {
9393
return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT;
9494
}
@@ -131,7 +131,7 @@ bool common_hal_digitalio_digitalinout_get_value(
131131

132132
void common_hal_digitalio_digitalinout_set_drive_mode(
133133
digitalio_digitalinout_obj_t* self,
134-
enum digitalio_drive_mode_t drive_mode) {
134+
digitalio_drive_mode_t drive_mode) {
135135
bool value = common_hal_digitalio_digitalinout_get_value(self);
136136
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
137137
// True is implemented differently between modes so reset the value to make
@@ -141,7 +141,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
141141
}
142142
}
143143

144-
enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
144+
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
145145
digitalio_digitalinout_obj_t* self) {
146146
if (self->open_drain) {
147147
return DRIVE_MODE_OPEN_DRAIN;
@@ -151,7 +151,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
151151
}
152152

153153
void common_hal_digitalio_digitalinout_set_pull(
154-
digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
154+
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
155155
enum port_pin_pull asf_pull = PORT_PIN_PULL_NONE;
156156
switch (pull) {
157157
case PULL_UP:
@@ -172,7 +172,7 @@ void common_hal_digitalio_digitalinout_set_pull(
172172
port_pin_set_config(self->pin->pin, &pin_conf);
173173
}
174174

175-
enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
175+
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
176176
digitalio_digitalinout_obj_t* self) {
177177
uint32_t pin = self->pin->pin;
178178
PortGroup *const port_base = port_get_group_from_gpio_pin(pin);

atmel-samd/common-hal/microcontroller/__init__.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626

2727
#include "py/mphal.h"
2828
#include "py/obj.h"
29+
#include "py/runtime.h"
2930

31+
#include "reset.h"
3032
#include "samd21_pins.h"
3133

3234
#include "shared-bindings/nvm/ByteArray.h"
35+
#include "shared-bindings/microcontroller/__init__.h"
3336
#include "shared-bindings/microcontroller/Processor.h"
3437

3538
void common_hal_mcu_delay_us(uint32_t delay) {
@@ -51,9 +54,33 @@ void common_hal_mcu_enable_interrupts(void) {
5154
cpu_irq_restore(irq_flags);
5255
}
5356

57+
extern uint32_t _ezero;
58+
extern uint32_t _srelocate;
59+
60+
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
61+
// Set up the defaults.
62+
_bootloader_dbl_tap = DBL_TAP_MAGIC;
63+
_ezero = CIRCUITPY_CANARY_WORD;
64+
65+
if (runmode == RUNMODE_BOOTLOADER) {
66+
if (&_bootloader_dbl_tap < &_srelocate) {
67+
mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
68+
}
69+
// Pretend to be the first of the two reset presses needed to enter the
70+
// bootloader. That way one reset will end in the bootloader.
71+
_bootloader_dbl_tap = DBL_TAP_MAGIC;
72+
} else if (runmode == RUNMODE_SAFE_MODE) {
73+
_ezero = CIRCUITPY_SOFTWARE_SAFE_MODE;
74+
}
75+
}
76+
77+
void common_hal_mcu_reset(void) {
78+
reset();
79+
}
80+
5481
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
5582
// It currently only has properties, and no state.
56-
mcu_processor_obj_t common_hal_mcu_processor_obj = {
83+
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
5784
.base = {
5885
.type = &mcu_processor_type,
5986
},
@@ -62,7 +89,7 @@ mcu_processor_obj_t common_hal_mcu_processor_obj = {
6289
// NVM is only available on Express boards for now.
6390
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
6491
// The singleton nvm.ByteArray object.
65-
nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
92+
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
6693
.base = {
6794
.type = &nvm_bytearray_type,
6895
},

atmel-samd/main.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ typedef enum {
8484
BROWNOUT,
8585
HARD_CRASH,
8686
USER_SAFE_MODE,
87+
SOFTWARE_SAFE_MODE
8788
} safe_mode_t;
8889

8990
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) {
375376
mp_hal_stdout_tx_str(".\r\n");
376377
} else
377378
#endif
378-
if (safe_mode != NO_SAFE_MODE) {
379+
if (safe_mode == SOFTWARE_SAFE_MODE) {
380+
mp_hal_stdout_tx_str("\r\nYou requested starting in safe mode from your software.");
381+
mp_hal_stdout_tx_str(".\r\nTo exit, please reset the board.\r\n");
382+
} else if (safe_mode != NO_SAFE_MODE) {
379383
mp_hal_stdout_tx_str("\r\nYou are running in safe mode which means something really bad happened.\r\n");
380384
if (safe_mode == HARD_CRASH) {
381385
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) {
524528
REG_MTB_MASTER = 0x00000000 + 6;
525529
#endif
526530

531+
// CIRCUITPY_SOFTWARE_SAFE_MODE works just like the canary except if it
532+
// survives we enter safe mode with a friendlier message.
533+
bool software_safe_mode = _ezero == CIRCUITPY_SOFTWARE_SAFE_MODE;
534+
527535
// On power on start or external reset, set _ezero to the canary word. If it
528-
// gets killed, we boot in safe mod. _ezero is the boundary between statically
529-
// allocated memory including the fixed MicroPython heap and the stack. If either
530-
// misbehaves, the canary will not be in tact after soft reset.
536+
// gets killed, we boot in safe mode. _ezero is the boundary between statically
537+
// allocated memory including the fixed MicroPython heap and the stack. If
538+
// either misbehaves, the canary will not be intact after soft reset.
531539
#ifdef CIRCUITPY_CANARY_WORD
532540
if (PM->RCAUSE.bit.POR == 1 || PM->RCAUSE.bit.EXT == 1) {
533541
_ezero = CIRCUITPY_CANARY_WORD;
@@ -607,6 +615,10 @@ safe_mode_t samd21_init(void) {
607615
return USER_SAFE_MODE;
608616
}
609617

618+
if (software_safe_mode) {
619+
return SOFTWARE_SAFE_MODE;
620+
}
621+
610622
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
611623
// Upgrade the nvm flash to include one sector for eeprom emulation.
612624
struct nvm_fusebits fuses;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy