diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h index 67cb80ebc9..5ade2804e3 100644 --- a/src/rp2350/pico_platform/include/pico/platform.h +++ b/src/rp2350/pico_platform/include/pico/platform.h @@ -189,7 +189,7 @@ __force_inline static bool pico_processor_state_is_nonsecure(void) { /*! \brief Returns the RP2350 chip revision number * \ingroup pico_platform - * @return the RP2350 chip revision number (1 for B0/B1, 2 for B2) + * @return the RP2350 chip revision number (2 for A2, 3 for A3/A4) */ uint8_t rp2350_chip_version(void); @@ -201,11 +201,11 @@ static inline uint8_t rp2040_chip_version(void) { return 2; } -/*! \brief Returns the RP2040 rom version number +/*! \brief Returns the RP2350 rom version number * \ingroup pico_platform - * @return the RP2040 rom version number (1 for RP2040-B0, 2 for RP2040-B1, 3 for RP2040-B2) + * @return the RP2350 rom version number (2 for RP2350-A2, 3 for RP2350-A3, 4 for RP2350-A4) */ -static inline uint8_t rp2040_rom_version(void) { +static inline uint8_t rp2350_rom_version(void) { GCC_Pragma("GCC diagnostic push") GCC_Pragma("GCC diagnostic ignored \"-Warray-bounds\"") return *(uint8_t*)0x13; diff --git a/src/rp2_common/pico_bootrom/bootrom.c b/src/rp2_common/pico_bootrom/bootrom.c index 766574802f..c9e59bfdad 100644 --- a/src/rp2_common/pico_bootrom/bootrom.c +++ b/src/rp2_common/pico_bootrom/bootrom.c @@ -31,6 +31,19 @@ bool rom_funcs_lookup(uint32_t *table, unsigned int count) { return ok; } +// The activity LED on RP2350 A2 QFN60 chips doesn't work in Arm mode, so boot into RISC-V if the user +// really, really wants the activity LED +#if PICO_RP2350_A2_SUPPORTED && PICO_RP2350A && !PICO_RISCV && PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG +#define rom_reboot_workaround(flags, delay_ms, p0, p1) ({ \ + if (((p0) & BOOTSEL_FLAG_GPIO_PIN_SPECIFIED) && rp2350_rom_version() == 2) \ + rom_reboot((flags) | REBOOT2_FLAG_REBOOT_TO_RISCV, delay_ms, p0, p1); \ + else \ + rom_reboot(flags, delay_ms, p0, p1); \ +}) +#else +#define rom_reboot_workaround(flags, delay_ms, p0, p1) rom_reboot(flags, delay_ms, p0, p1) +#endif + void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) { #ifdef ROM_FUNC_RESET_USB_BOOT @@ -43,7 +56,7 @@ void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin // the parameter is actually the gpio number, but we only care if BOOTSEL_FLAG_GPIO_PIN_SPECIFIED usb_activity_gpio_pin_mask = (uint32_t)__builtin_ctz(usb_activity_gpio_pin_mask); } - rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, usb_activity_gpio_pin_mask); + rom_reboot_workaround(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, usb_activity_gpio_pin_mask); __builtin_unreachable(); #else panic_unsupported(); @@ -63,7 +76,7 @@ void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pi flags |= BOOTSEL_FLAG_GPIO_PIN_ACTIVE_LOW; } } - rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, (uint)usb_activity_gpio_pin); + rom_reboot_workaround(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, (uint)usb_activity_gpio_pin); __builtin_unreachable(); #else panic_unsupported(); diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom.h b/src/rp2_common/pico_bootrom/include/pico/bootrom.h index 667cece174..6223d92f4b 100644 --- a/src/rp2_common/pico_bootrom/include/pico/bootrom.h +++ b/src/rp2_common/pico_bootrom/include/pico/bootrom.h @@ -241,6 +241,13 @@ static __force_inline void *rom_data_lookup_inline(uint32_t code) { } #pragma GCC diagnostic pop +#if PICO_RP2350 +// PICO_CONFIG: PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG, Workaround RP2350A-A2 (QFN60) bug not displaying USB boot activity LED under Arm by making rom_reset_usb_boot functions reboot to RISC-V when the activity LED is specified, type=bool, default=1, group=pico_bootrom +#ifndef PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG +#define PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG 1 +#endif +#endif + /*! * \brief Reboot the device into BOOTSEL mode * \ingroup pico_bootrom @@ -250,7 +257,13 @@ static __force_inline void *rom_data_lookup_inline(uint32_t code) { * 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_mask 0 No pins are used as per a cold boot. Otherwise a single bit set indicating which + * \if rp2350_specific + * \note On RP2350A-A2 chips, errata RP2350-E3 prevents the activity LED working under Arm. + * PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG=1 is defined by default to have this method reboot to + * RISC-V USB boot to display the activity LED correctly. + * \endif + * + * \param usb_activity_gpio_pin_mask 0 No pins are used as per a cold boot. Otherwise, a single bit set indicating which * GPIO pin should be set to output and raised whenever there is mass storage activity * from the host. * \param disable_interface_mask value to control exposed interfaces @@ -272,13 +285,19 @@ static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activit * 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. * + * \if rp2350_specific + * \note On RP2350A-A2 chips, errata RP2350-E3 prevents the activity LED working under Arm. + * PICO_BOOTROM_WORKAROUND_RP2350_A2_ACTIVITY_LED_BUG=1 is defined by default to have this method reboot to + * RISC-V USB boot to display the activity LED correctly. + * \endif + * * \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) + * \param usb_activity_gpio_pin_active_low Activity GPIO is active low (ignored on RP2040). A bug in the bootrom of RP2350 + * A4 chips means this parameter has no effect on that version of the RP2350. */ 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);