-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add support for resetting RP2040 via the USB connection when using pi… #197
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ | |
* Note this library is a developer convenience. It is not applicable in all cases; for one it takes full control of the USB device precluding your | ||
* use of the USB in device or host mode. For this reason, this library will automatically disengage if you try to using it alongside \ref tinyusb_device or | ||
* \ref tinyusb_host. It also takes control of a lower level IRQ and sets up a periodic background task. | ||
* | ||
* This library also includes (by default) functionality to enable the RP2040 to be reset over the USB interface. | ||
*/ | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_DEFAULT_CRLF, Default state of CR/LF translation for USB output, type=bool, default=PICO_STDIO_DEFAULT_CRLF, group=pico_stdio_usb | ||
|
@@ -31,7 +33,7 @@ | |
#define PICO_STDIO_USB_STDOUT_TIMEOUT_US 500000 | ||
#endif | ||
|
||
// todo perhaps unnecessarily high? | ||
// todo perhaps unnecessarily frequent? | ||
// PICO_CONFIG: PICO_STDIO_USB_TASK_INTERVAL_US, Period of microseconds between calling tud_task in the background, default=1000, advanced=true, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_TASK_INTERVAL_US | ||
#define PICO_STDIO_USB_TASK_INTERVAL_US 1000 | ||
|
@@ -42,6 +44,36 @@ | |
#define PICO_STDIO_USB_LOW_PRIORITY_IRQ 31 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE, Enable/disable resetting into BOOTSEL mode if the host sets the baud rate to a magic value (PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE), type=bool, default=1, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE | ||
#define PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE 1 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE, baud rate that if selected causes a reset into BOOTSEL mode (if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE==1), default=1200, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE | ||
#define PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE 1200 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE, Enable/disable resetting into BOOTSEL mode via an additional VENDOR USB interface - enables picotool based reset, type=bool, default=1, group=pico_stdio_usb | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (this was fixed in #206 ) |
||
#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE | ||
#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 1 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL, If vendor reset interface is included allow rebooting to BOOTSEL mode, type=bool, default=1, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL | ||
#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL 1 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT, If vendor reset interface is included allow rebooting with regular flash boot, type=bool, default=1, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT | ||
#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT 1 | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS, delays in ms before rebooting via regular flash boot, default=100, group=pico_stdio_usb | ||
#ifndef PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS | ||
#define PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS 100 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just out of curiosity, why would somebody ever need/want to change this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the probably don't, but no harm in creating a define since I picked an arbitrary value |
||
#endif | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
#ifndef _PICO_STDIO_USB_RESET_INTERFACE_H | ||
#define _PICO_STDIO_USB_RESET_INTERFACE_H | ||
|
||
// We use VENDOR, 0, 0 for PICOBOOT, so lets use VENDOR, 0, 1 for RESET | ||
|
||
// VENDOR sub-class for the reset interface | ||
#define RESET_INTERFACE_SUBCLASS 0x00 | ||
// VENDOR protocol for the reset interface | ||
#define RESET_INTERFACE_PROTOCOL 0x01 | ||
|
||
// CONTROL requests: | ||
|
||
// reset to BOOTSEL | ||
#define RESET_REQUEST_BOOTSEL 0x01 | ||
// regular flash boot | ||
#define RESET_REQUEST_FLASH 0x02 | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** | ||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
#include "tusb.h" | ||
|
||
#if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE | ||
#include "pico/bootrom.h" | ||
#include "pico/stdio_usb/reset_interface.h" | ||
#include "hardware/watchdog.h" | ||
#include "device/usbd_pvt.h" | ||
|
||
static uint8_t itf_num; | ||
|
||
static void resetd_init(void) { | ||
} | ||
|
||
static void resetd_reset(uint8_t __unused rhport) { | ||
itf_num = 0; | ||
} | ||
|
||
static uint16_t resetd_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { | ||
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass && | ||
RESET_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass && | ||
RESET_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0); | ||
|
||
uint16_t const drv_len = sizeof(tusb_desc_interface_t); | ||
TU_VERIFY(max_len >= drv_len, 0); | ||
|
||
itf_num = itf_desc->bInterfaceNumber; | ||
return drv_len; | ||
} | ||
|
||
// Support for parameterized reset via vendor interface control request | ||
static bool resetd_control_request_cb(uint8_t __unused rhport, tusb_control_request_t const *request) { | ||
if (request->wIndex == itf_num) { | ||
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL | ||
if (request->bRequest == RESET_REQUEST_BOOTSEL) { | ||
uint gpio_mask = 0; | ||
if (request->wValue & 0x100) { | ||
gpio_mask = 1u << (request->wValue >> 9u); | ||
} | ||
reset_usb_boot(gpio_mask, request->wValue & 0x7f); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does there need to be some comments about what |
||
// does not return, otherwise we'd return true | ||
} | ||
#endif | ||
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT | ||
if (request->bRequest == RESET_REQUEST_FLASH) { | ||
watchdog_reboot(0, SRAM_END, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS); | ||
return true; | ||
} | ||
#endif | ||
} | ||
return false; | ||
} | ||
|
||
static bool resetd_control_complete_cb(uint8_t __unused rhport, tusb_control_request_t __unused const *request) { | ||
return true; | ||
} | ||
|
||
static bool resetd_xfer_cb(uint8_t __unused rhport, uint8_t __unused ep_addr, xfer_result_t __unused result, uint32_t __unused xferred_bytes) { | ||
return true; | ||
} | ||
|
||
static usbd_class_driver_t const _resetd_driver = | ||
{ | ||
#if CFG_TUSB_DEBUG >= 2 | ||
.name = "RESET", | ||
#endif | ||
.init = resetd_init, | ||
.reset = resetd_reset, | ||
.open = resetd_open, | ||
.control_request = resetd_control_request_cb, | ||
.control_complete = resetd_control_complete_cb, | ||
.xfer_cb = resetd_xfer_cb, | ||
.sof = NULL | ||
}; | ||
|
||
// Implement callback to add our custom driver | ||
usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) { | ||
*driver_count = 1; | ||
return &_resetd_driver; | ||
} | ||
#endif | ||
|
||
#if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE | ||
// Support for default BOOTSEL reset by changing baud rate | ||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { | ||
if (p_line_coding->bit_rate == PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE) { | ||
reset_usb_boot(0, 0); | ||
} | ||
} | ||
#endif | ||
|
Uh oh!
There was an error while loading. Please reload this page.