rp2040: Add rp2350 specific mechanism for checking for double reset tap

It appears the rp2350 disables SRAM power when the RUN pin is pulled
low.  As a result, one can not store a code in regular memory to
detect if the RUN pin is pulled low multiple times.

Add a new CONFIG_HAVE_BOARD_CHECK_DOUBLE_RESET mechanism to allow the
board code to override the standard double reset checking code.
Implement an rp2350 specific check that uses the chip's POWMAN
chip_reset field to store/check a double reset condition.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2024-12-12 11:22:31 -05:00 committed by Eric Callahan
parent c0014efc4a
commit aa37e30b71
6 changed files with 44 additions and 6 deletions

View File

@ -120,6 +120,9 @@ config BUILD_DEPLOYER
config HAVE_CHIPID config HAVE_CHIPID
bool bool
default n default n
config HAVE_BOARD_CHECK_DOUBLE_RESET
bool
default n
config KATAPULT_VERSION config KATAPULT_VERSION
string string

View File

@ -32,11 +32,14 @@ check_button_pressed(void)
#define DOUBLE_CLICK_MAX_US 500000 #define DOUBLE_CLICK_MAX_US 500000
// Check for a bootloader request via double tap of reset button // Check for a bootloader request via double tap of reset button
static void static int
check_double_reset(void) check_double_reset(void)
{ {
if (!CONFIG_ENABLE_DOUBLE_RESET) if (!CONFIG_ENABLE_DOUBLE_RESET)
return; return 0;
if (CONFIG_HAVE_BOARD_CHECK_DOUBLE_RESET)
// Use board specific detection mechanism
return board_check_double_reset();
// Set request signature and delay - this enters the bootloader if // Set request signature and delay - this enters the bootloader if
// the reset button is double clicked // the reset button is double clicked
udelay(DOUBLE_CLICK_MIN_US); udelay(DOUBLE_CLICK_MIN_US);
@ -44,6 +47,7 @@ check_double_reset(void)
udelay(DOUBLE_CLICK_MAX_US - DOUBLE_CLICK_MIN_US); udelay(DOUBLE_CLICK_MAX_US - DOUBLE_CLICK_MIN_US);
// No reset, clear the bootup code // No reset, clear the bootup code
set_bootup_code(0); set_bootup_code(0);
return 0;
} }
// Check if bootloader or application should be started // Check if bootloader or application should be started
@ -60,8 +64,5 @@ bootentry_check(void)
set_bootup_code(0); set_bootup_code(0);
return 1; return 1;
} }
check_double_reset(); return check_double_reset();
// jump to app
return 0;
} }

View File

@ -2,5 +2,6 @@
#define __BOOTENTRY_H #define __BOOTENTRY_H
int bootentry_check(void); int bootentry_check(void);
int board_check_double_reset(void);
#endif // bootentry.h #endif // bootentry.h

View File

@ -7,6 +7,7 @@ config RPXXXX_SELECT
default y default y
select HAVE_GPIO select HAVE_GPIO
select HAVE_CHIPID select HAVE_CHIPID
select HAVE_BOARD_CHECK_DOUBLE_RESET if MACH_RP2350
config BOARD_DIRECTORY config BOARD_DIRECTORY
string string

View File

@ -21,6 +21,7 @@ mcu-y += generic/armcm_irq.c generic/crc16_ccitt.c
mcu-y += ../lib/pico-sdk/hardware/flash.c mcu-y += ../lib/pico-sdk/hardware/flash.c
mcu-$(CONFIG_MACH_RP2040) += rp2040/timer.c rp2040/bootrom.c mcu-$(CONFIG_MACH_RP2040) += rp2040/timer.c rp2040/bootrom.c
mcu-$(CONFIG_MACH_RP2350) += generic/armcm_timer.c rp2040/rp2350_bootrom.c mcu-$(CONFIG_MACH_RP2350) += generic/armcm_timer.c rp2040/rp2350_bootrom.c
mcu-$(CONFIG_MACH_RP2350) += rp2040/rp2350_dblreset.c
src-y += generic/armcm_canboot.c $(mcu-y) src-y += generic/armcm_canboot.c $(mcu-y)
src-$(CONFIG_USBSERIAL) += rp2040/usbserial.c generic/usb_cdc.c rp2040/chipid.c src-$(CONFIG_USBSERIAL) += rp2040/usbserial.c generic/usb_cdc.c rp2040/chipid.c

View File

@ -0,0 +1,31 @@
// rp2350 specific handling for checking if double reset occurred
//
// Copyright (C) 2024 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include <stdint.h> // uint32_t
#include "bootentry.h" // board_check_double_reset
#include "canboot.h" // udelay
#include "hardware/structs/powman.h" // powman_hw
#define DOUBLE_CLICK_MIN_US 10000
#define DOUBLE_CLICK_MAX_US 500000
int
board_check_double_reset(void)
{
if (powman_hw->chip_reset & POWMAN_CHIP_RESET_DOUBLE_TAP_BITS) {
// Double reset detected - clear flag and enter bootloader
powman_hw->chip_reset = 0x5afe0000;
return 1;
}
// Initial delay (reset in under 10ms isn't a "double tap")
udelay(DOUBLE_CLICK_MIN_US);
// Set the DOUBLE_TAP_BITS bits
powman_hw->chip_reset = 0x5afe0001;
udelay(DOUBLE_CLICK_MAX_US - DOUBLE_CLICK_MIN_US);
// No reset, clear the DOUBLE_TAP_BITS bits
powman_hw->chip_reset = 0x5afe0000;
return 0;
}