diff --git a/rtlplayground.c b/rtlplayground.c index 358650d..2355854 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -30,6 +30,8 @@ extern __xdata uint32_t flash_size; extern __xdata uint16_t crc_value; __xdata struct machine_runtime machine_detected; void crc16(__xdata uint8_t *v) __naked; +void flash_default_config(void); +void early_boot_handle_button(void); // See setup_serial_timer1() for valid baudrate settings! #define SERIAL_BAUD_RATE 115200 @@ -735,6 +737,64 @@ void delay(uint16_t t) PCON |= 1; } +void early_boot_handle_button(void) +{ + if (machine.reset_pin == GPIO_NA) + return; + + gpio_input_setup(machine.reset_pin); + + // Debounce after init + delay(100); + // If the button is not already held at boot, continue normally. + if (gpio_pin_test(machine.reset_pin)) + return; + + set_sys_led_state(SYS_LED_FAST); + print_string("\n[Reset button held at boot]\n"); + + if (gpio_pin_test(machine.reset_pin)) + return; + + const __xdata uint32_t min_hold_ticks = 10UL * SYS_TICK_HZ; + const __xdata uint32_t max_hold_ticks = 30UL * SYS_TICK_HZ; + const __xdata uint32_t blink_ticks = SYS_TICK_HZ / 10; // 100 ms + const __xdata uint32_t pause_ticks = SYS_TICK_HZ / 2; // 500 ms + __xdata uint32_t start_ticks = ticks; + __xdata uint32_t last_blink_step = start_ticks; + __xdata uint8_t blink_step = 0; + + set_sys_led_state(SYS_LED_ON); + + while (!gpio_pin_test(machine.reset_pin)) { + __xdata uint32_t held_ticks = ticks - start_ticks; + + if (held_ticks > max_hold_ticks) { + print_string("[Button held >30s at boot; continuing normal boot]\n"); + return; + } + + // Double blink pattern while button is held: + // ON (100ms), OFF (100ms), ON (100ms), OFF (500ms) + __xdata uint32_t step_ticks = (blink_step == 3) ? pause_ticks : blink_ticks; + if ((ticks - last_blink_step) >= step_ticks) { + blink_step = (blink_step + 1) & 0x3; + set_sys_led_state((blink_step == 0 || blink_step == 2) ? SYS_LED_ON : SYS_LED_OFF); + last_blink_step = ticks; + } + + PCON |= 1; + } + + set_sys_led_state(SYS_LED_ON); + + if ((ticks - start_ticks) >= min_hold_ticks) { + print_string("[Button held 10s-30s at boot; restoring default config]\n"); + set_sys_led_state(SYS_LED_FAST); + flash_default_config(); + delay(3UL * SYS_TICK_HZ); + } +} /* * Configure the SerDes of the SoC for a particular mode @@ -2134,6 +2194,8 @@ void main(void) // p031f.a610:2058 p041f.a610:2058 p051f.a610:2058 r4f3c:00000000 p061f.a610:2058 p071f.a610:2058 port_stats_print(); + early_boot_handle_button(); + execute_config(); print_string("\n> "); idle_ready = 1;