Skip to content

Fix two watchdog crashes #5272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/utils/pyexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,21 @@ int pyexec_friendly_repl(void) {
}

vstr_reset(&line);
int ret = readline(&line, ">>> ");

nlr_buf_t nlr;
nlr.ret_val = NULL;
int ret = 0;
if (nlr_push(&nlr) == 0) {
ret = readline(&line, ">>> ");
} else {
// Uncaught exception
mp_handle_pending(false); // clear any pending exceptions (and run any callbacks)

// Print exceptions but stay in the REPL. There are very few delayed
// exceptions. The WatchDogTimer can raise one though.
mp_hal_stdout_tx_str("\r\n");
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
}
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;

if (ret == CHAR_CTRL_A) {
Expand Down
1 change: 1 addition & 0 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -3939,6 +3939,7 @@ msgstr ""
#: ports/esp32s2/boards/gravitech_cucumber_r/mpconfigboard.h
#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h
#: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/esp32s2/boards/lolin_s2_mini/mpconfigboard.h
#: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h
#: ports/esp32s2/boards/morpheans_morphesp-240/mpconfigboard.h
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h
Expand Down
3 changes: 3 additions & 0 deletions ports/atmel-samd/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@

#define MICROPY_FATFS_EXFAT 0

// Only support simpler HID descriptors on SAMD21.
#define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (1)

#endif // SAMD21

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 6 additions & 1 deletion ports/nrf/common-hal/watchdog/WatchDogTimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <math.h>
#include <string.h>

#include "py/gc.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
Expand Down Expand Up @@ -94,7 +95,11 @@ void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) {

void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) {
if (self->mode == WATCHDOGMODE_RESET) {
mp_raise_NotImplementedError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET"));
if (gc_alloc_possible()) {
mp_raise_NotImplementedError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET"));
}
// Don't change anything because RESET cannot be undone.
return;
}
if (timer) {
timer_free();
Expand Down
17 changes: 17 additions & 0 deletions py/circuitpy_mpconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,13 @@ void supervisor_run_background_tasks_if_tick(void);

#define CIRCUITPY_VERBOSE_BLE 0

// This trades ~1k flash space (1) for that much in RAM plus the cost to compute
// the values once on init (0). Only turn it off, when you really need the flash
// space and are willing to trade the RAM.
#ifndef CIRCUITPY_PRECOMPUTE_QSTR_ATTR
#define CIRCUITPY_PRECOMPUTE_QSTR_ATTR (1)
#endif

// USB settings

// If the port requires certain USB endpoint numbers, define these in mpconfigport.h.
Expand Down Expand Up @@ -761,6 +768,16 @@ void supervisor_run_background_tasks_if_tick(void);
#define USB_HID_EP_NUM_IN (0)
#endif

// The most complicated device currently known of is the head and eye tracker, which requires 5
// report ids.
// https://usb.org/sites/default/files/hutrr74_-_usage_page_for_head_and_eye_trackers_0.pdf
// The default descriptors only use 1, so that is the minimum.
#ifndef CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR
#define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (6)
#elif CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR < 1
#error "CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR must be at least 1"
#endif

#ifndef USB_MIDI_EP_NUM_OUT
#define USB_MIDI_EP_NUM_OUT (0)
#endif
Expand Down
20 changes: 18 additions & 2 deletions py/qstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ mp_uint_t qstr_compute_hash(const byte *data, size_t len) {
}
return hash;
}

const qstr_attr_t mp_qstr_const_attr[] = {
#ifndef CIRCUITPY_PRECOMPUTE_QSTR_ATTR
#define CIRCUITPY_PRECOMPUTE_QSTR_ATTR (1)
#endif
#if CIRCUITPY_PRECOMPUTE_QSTR_ATTR == 1
const qstr_attr_t mp_qstr_const_attr[MP_QSTRnumber_of] = {
#ifndef NO_QSTR
#define QDEF(id, hash, len, str) { hash, len },
#define TRANSLATION(id, length, compressed ...)
Expand All @@ -86,6 +89,9 @@ const qstr_attr_t mp_qstr_const_attr[] = {
#undef QDEF
#endif
};
#else
qstr_attr_t mp_qstr_const_attr[MP_QSTRnumber_of];
#endif

const qstr_pool_t mp_qstr_const_pool = {
NULL, // no previous pool
Expand Down Expand Up @@ -115,6 +121,16 @@ void qstr_init(void) {
MP_STATE_VM(last_pool) = (qstr_pool_t *)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left
MP_STATE_VM(qstr_last_chunk) = NULL;

#if CIRCUITPY_PRECOMPUTE_QSTR_ATTR == 0
if (mp_qstr_const_attr[MP_QSTR_circuitpython].len == 0) {
for (size_t i = 0; i < mp_qstr_const_pool.len; i++) {
size_t len = strlen(mp_qstr_const_pool.qstrs[i]);
mp_qstr_const_attr[i].hash = qstr_compute_hash((const byte *)mp_qstr_const_pool.qstrs[i], len);
mp_qstr_const_attr[i].len = len;
}
}
#endif

#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex));
#endif
Expand Down
14 changes: 7 additions & 7 deletions shared-module/usb_hid/Device.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const usb_hid_device_obj_t usb_hid_device_keyboard_obj = {
.usage = 0x06,
.num_report_ids = 1,
.report_ids = { 0x01, },
.in_report_lengths = { 8, 0, 0, 0, 0, 0, },
.in_report_lengths = { 8, },
.out_report_lengths = { 1, },
};

Expand Down Expand Up @@ -131,7 +131,7 @@ const usb_hid_device_obj_t usb_hid_device_mouse_obj = {
.usage = 0x02,
.num_report_ids = 1,
.report_ids = { 0x02, },
.in_report_lengths = { 4, 0, 0, 0, 0, 0, },
.in_report_lengths = { 4, },
.out_report_lengths = { 0, },
};

Expand Down Expand Up @@ -160,7 +160,7 @@ const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = {
.usage = 0x01,
.num_report_ids = 1,
.report_ids = { 0x03 },
.in_report_lengths = { 2, 0, 0, 0, 0, 0, },
.in_report_lengths = { 2, },
.out_report_lengths = { 0, },
};

Expand All @@ -170,7 +170,7 @@ STATIC size_t get_report_id_idx(usb_hid_device_obj_t *self, size_t report_id) {
return i;
}
}
return MAX_REPORT_IDS_PER_DESCRIPTOR;
return CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR;
}

// See if report_id is used by this device. If it is -1, then return the sole report id used by this device,
Expand All @@ -180,16 +180,16 @@ uint8_t common_hal_usb_hid_device_validate_report_id(usb_hid_device_obj_t *self,
return self->report_ids[0];
}
if (!(report_id_arg >= 0 &&
get_report_id_idx(self, (size_t)report_id_arg) < MAX_REPORT_IDS_PER_DESCRIPTOR)) {
get_report_id_idx(self, (size_t)report_id_arg) < CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR)) {
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_report_id);
}
return (uint8_t)report_id_arg;
}

void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t report_descriptor, uint8_t usage_page, uint8_t usage, size_t num_report_ids, uint8_t *report_ids, uint8_t *in_report_lengths, uint8_t *out_report_lengths) {
if (num_report_ids > MAX_REPORT_IDS_PER_DESCRIPTOR) {
if (num_report_ids > CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR) {
mp_raise_ValueError_varg(translate("More than %d report ids not supported"),
MAX_REPORT_IDS_PER_DESCRIPTOR);
CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR);
}

// report buffer pointers are NULL at start, and are created when USB is initialized.
Expand Down
15 changes: 5 additions & 10 deletions shared-module/usb_hid/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,16 @@

#include "py/obj.h"

// The most complicated device currently known of is the head and eye tracker, which requires 5
// report ids.
// https://usb.org/sites/default/files/hutrr74_-_usage_page_for_head_and_eye_trackers_0.pdf
#define MAX_REPORT_IDS_PER_DESCRIPTOR (6)

typedef struct {
mp_obj_base_t base;
// Python buffer object whose contents are the descriptor.
const uint8_t *report_descriptor;
uint8_t *in_report_buffers[MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t *out_report_buffers[MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t *in_report_buffers[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t *out_report_buffers[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
uint16_t report_descriptor_length;
uint8_t report_ids[MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t in_report_lengths[MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t out_report_lengths[MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t report_ids[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t in_report_lengths[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t out_report_lengths[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
uint8_t usage_page;
uint8_t usage;
uint8_t num_report_ids;
Expand Down