Skip to content

Commit

Permalink
add rom_reset_usb_boot_extra which supports >32 pins and ACTIVE_LOW; …
Browse files Browse the repository at this point in the history
…change existing uses to use this (#2084)
  • Loading branch information
kilograham authored Nov 21, 2024
1 parent 6bb3ccf commit 5a98889
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 12 deletions.
20 changes: 20 additions & 0 deletions src/rp2_common/pico_bootrom/bootrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin
#endif
}

void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pin, uint32_t disable_interface_mask, bool usb_activity_gpio_pin_active_low) {
#ifdef ROM_FUNC_RESET_USB_BOOT
(void)usb_activity_gpio_pin_active_low;
rom_reset_usb_boot_fn func = (rom_reset_usb_boot_fn) rom_func_lookup(ROM_FUNC_RESET_USB_BOOT);
func(usb_activity_gpio_pin < 0 ? 0 : (1u << usb_activity_gpio_pin), disable_interface_mask);
#elif defined(ROM_FUNC_REBOOT)
uint32_t flags = disable_interface_mask;
if (usb_activity_gpio_pin >= 0) {
flags |= BOOTSEL_FLAG_GPIO_PIN_SPECIFIED;
if (usb_activity_gpio_pin_active_low) {
flags |= BOOTSEL_FLAG_GPIO_PIN_ACTIVE_LOW;
}
}
rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, usb_activity_gpio_pin);
__builtin_unreachable();
#else
panic_unsupported();
#endif
}

#if !PICO_RP2040
bool rom_get_boot_random(uint32_t out[4]) {
uint32_t result[5];
Expand Down
19 changes: 19 additions & 0 deletions src/rp2_common/pico_bootrom/include/pico/bootrom.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,25 @@ static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activit
rom_reset_usb_boot(usb_activity_gpio_pin_mask, disable_interface_mask);
}

/*!
* \brief Reboot the device into BOOTSEL mode
* \ingroup pico_bootrom
*
* This function reboots the device into the BOOTSEL mode ('usb boot").
*
* Facilities are provided to enable an "activity light" via GPIO attached LED for the USB Mass Storage Device,
* and to limit the USB interfaces exposed.
*
* \param usb_activity_gpio_pin GPIO pin to be used as an activitiy pin, or -1 for none
* from the host.
* \param disable_interface_mask value to control exposed interfaces
* - 0 To enable both interfaces (as per a cold boot)
* - 1 To disable the USB Mass Storage Interface
* - 2 To disable the USB PICOBOOT Interface
* \param usb_activity_gpio_pin_active_low Activity GPIO is active low (ignored on RP2040)
*/
void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pin, uint32_t disable_interface_mask, bool usb_activity_gpio_pin_active_low);

/*!
* \brief Connect the SSI/QMI to the QSPI pads
* \ingroup pico_bootrom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@

// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_bootsel_via_double_reset

// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW, Whether pin used as bootloader activity LED when BOOTSEL mode is entered via reset double tap is active low. Not supported on RP2040, type=bool, default=0, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW 0
#endif

// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via double reset, type=int, min=0, max=3, default=0, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK 0u
Expand Down Expand Up @@ -127,13 +132,14 @@ static void __attribute__((constructor)) boot_double_tap_check(void) {
// Detected a double reset, so enter USB bootloader
clear_double_tap_flag();
#ifdef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED
const uint32_t led_mask = 1u << PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
const int led = PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
#else
const uint32_t led_mask = 0u;
const int led = -1;
#endif
reset_usb_boot(
led_mask,
PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
rom_reset_usb_boot_extra(
led,
PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK,
PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW
);
}

Expand Down
5 changes: 5 additions & 0 deletions src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@

// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdio_usb

// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW, Whether pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE) is active low, type=bool, default=0, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED_ACTIVE_LOW
#define PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED_ACTIVE_LOW 0
#endif

// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
#define PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED 0
Expand Down
19 changes: 12 additions & 7 deletions src/rp2_common/pico_stdio_usb/reset_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,19 @@ static bool resetd_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL
if (request->bRequest == RESET_REQUEST_BOOTSEL) {
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
int gpio = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
bool active_low = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW;
#else
uint gpio_mask = 0u;
int gpio = -1;
bool active_low = false;
#endif
#if !PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
if (request->wValue & 0x100) {
gpio_mask = 1u << (request->wValue >> 9u);
gpio = request->wValue >> 9u;
}
active_low = request->wValue & 0x200;
#endif
reset_usb_boot(gpio_mask, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
rom_reset_usb_boot_extra(gpio, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, active_low);
// does not return, otherwise we'd return true
}
#endif
Expand Down Expand Up @@ -173,11 +176,13 @@ usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
void tud_cdc_line_coding_cb(__unused uint8_t itf, cdc_line_coding_t const* p_line_coding) {
if (p_line_coding->bit_rate == PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE) {
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
const uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
int gpio = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
bool active_low = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW;
#else
const uint gpio_mask = 0u;
int gpio = -1;
bool active_low = false;
#endif
reset_usb_boot(gpio_mask, PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
rom_reset_usb_boot_extra(gpio, PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, active_low);
}
}
#endif
Expand Down

0 comments on commit 5a98889

Please sign in to comment.