// Determine if the bootloader or application should start // // Copyright (C) 2021 Eric Callahan // // This file may be distributed under the terms of the GNU GPLv3 license. #include // strlen #include "autoconf.h" // CONFIG_* #include "board/flash.h" // flash_read_block #include "board/gpio.h" // gpio_in_setup #include "board/misc.h" // set_bootup_code #include "bootentry.h" // bootentry_check #include "canboot.h" // udelay #include "ctr.h" // DECL_CTR // Generated by buildcommands.py DECL_CTR("DECL_BUTTON " __stringify(CONFIG_BUTTON_PIN)); extern int32_t button_gpio, button_high, button_pullup; // Check for a bootloader request via double tap of reset button static int check_button_pressed(void) { if (!CONFIG_ENABLE_BUTTON) return 0; struct gpio_in button = gpio_in_setup(button_gpio, button_pullup); udelay(10); return gpio_in_read(button) == button_high; } #define DOUBLE_CLICK_MIN_US 10000 #define DOUBLE_CLICK_MAX_US 500000 // Check for a bootloader request via double tap of reset button static void check_double_reset(void) { if (!CONFIG_ENABLE_DOUBLE_RESET) return; // Set request signature and delay - this enters the bootloader if // the reset button is double clicked udelay(DOUBLE_CLICK_MIN_US); set_bootup_code(REQUEST_CANBOOT); udelay(DOUBLE_CLICK_MAX_US - DOUBLE_CLICK_MIN_US); // No reset, clear the bootup code set_bootup_code(0); } // Check if bootloader or application should be started int bootentry_check(void) { // Enter the bootloader in the following conditions: // - The request signature is set in memory (request from app) // - No application code is present uint64_t bootup_code = get_bootup_code(); if (bootup_code == REQUEST_CANBOOT || !application_check_valid() || check_button_pressed()) { // Start bootloader main loop set_bootup_code(0); return 1; } check_double_reset(); // jump to app return 0; }