Customize boot mode

jasper.z
Posts: 4
Joined: Tue Mar 27, 2018 2:13 am

Customize boot mode

Postby jasper.z » Tue Mar 27, 2018 2:23 am

Hey Guys,
As i knows,there are two boot mode currenlty:
boot mode
11 : Flash download mode
31 : Flash boot mode

I'd like to implement third option: factory mode which would be used for verifying functionality on production line. The initial idea is to detect status of key pressing on bootloader phase and jump into responding partition , Is that feasible?

I just saw the description as below on ESP-IDF Programming Guide,i'm not sure it has already proved my idea unfeasible. If so ,do you have any other recommended solution?

"Currently it is not possible to add application-defined hooks to the bootloader to customize application partition selection logic. This may be required to load different application image depending on a state of a GPIO"
http://esp-idf.readthedocs.io/en/latest ... bootloader

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: Customize boot mode

Postby WiFive » Tue Mar 27, 2018 5:59 am

Those modes are from rom bootloader, but you can copy (2nd stage) bootloader component to your project and edit it however you want

jasper.z
Posts: 4
Joined: Tue Mar 27, 2018 2:13 am

Re: Customize boot mode

Postby jasper.z » Tue Mar 27, 2018 7:12 am

i know how to edit bootloader 2nd stage source,but the key issue is how to detect status of key pressing(state of a GPIO) on bootloader 2nd stage?

User avatar
loboris
Posts: 514
Joined: Wed Dec 21, 2016 7:40 pm

Re: Customize boot mode

Postby loboris » Tue Mar 27, 2018 12:10 pm

Here is the example of what I'm using to force boot to factory partition (in bootloader_start.c, function get_selected_boot_partition(const bootloader_state_t *bs)):

Code: Select all

/** LoBo
 *  @function :     ForceFactoryBoot
 *  @description:   Add by Imtiaz @ Syrp for failsafe mode
 *
 *  @inputs:        void
 */
const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
    IO_MUX_GPIO0_REG,
    IO_MUX_GPIO1_REG,
    IO_MUX_GPIO2_REG,
    IO_MUX_GPIO3_REG,
    IO_MUX_GPIO4_REG,
    IO_MUX_GPIO5_REG,
    IO_MUX_GPIO6_REG,
    IO_MUX_GPIO7_REG,
    IO_MUX_GPIO8_REG,
    IO_MUX_GPIO9_REG,
    IO_MUX_GPIO10_REG,
    IO_MUX_GPIO11_REG,
    IO_MUX_GPIO12_REG,
    IO_MUX_GPIO13_REG,
    IO_MUX_GPIO14_REG,
    IO_MUX_GPIO15_REG,
    IO_MUX_GPIO16_REG,
    IO_MUX_GPIO17_REG,
    IO_MUX_GPIO18_REG,
    IO_MUX_GPIO19_REG,
    0,
    IO_MUX_GPIO21_REG,
    IO_MUX_GPIO22_REG,
    IO_MUX_GPIO23_REG,
    0,
    IO_MUX_GPIO25_REG,
    IO_MUX_GPIO26_REG,
    IO_MUX_GPIO27_REG,
    0,
    0,
    0,
    0,
    IO_MUX_GPIO32_REG,
    IO_MUX_GPIO33_REG,
    IO_MUX_GPIO34_REG,
    IO_MUX_GPIO35_REG,
    IO_MUX_GPIO36_REG,
    IO_MUX_GPIO37_REG,
    IO_MUX_GPIO38_REG,
    IO_MUX_GPIO39_REG,
};

static uint8_t ForceFactoryBoot(void)
{
    #if CONFIG_GPIO_INPUT_FORCE_FACTORY
    uint8_t timer = 0;
    uint32_t mux_reg = GPIO_PIN_MUX_REG[CONFIG_GPIO_PIN_FORCE_FACTORY];
    if (mux_reg == 0) return 0;

    /*if (CONFIG_GPIO_PIN_FORCE_FACTORY < 28)*/ gpio_pad_select_gpio(CONFIG_GPIO_PIN_FORCE_FACTORY);
    //output disable
    if (CONFIG_GPIO_PIN_FORCE_FACTORY < 32) gpio_output_set(0,0,0, 1<<CONFIG_GPIO_PIN_FORCE_FACTORY);
    else gpio_output_set_high(0,0,0, 1<<(CONFIG_GPIO_PIN_FORCE_FACTORY-32));
    // Enable input
    PIN_INPUT_ENABLE(mux_reg);

    ets_delay_us(10000); //delay 10 msecs

    ESP_LOGI(TAG, "Check force Factory boot Pin %d for level %d [current=%d]",
             CONFIG_GPIO_PIN_FORCE_FACTORY, CONFIG_GPIO_LEVEL_FORCE_FACTORY, GPIO_INPUT_GET(CONFIG_GPIO_PIN_FORCE_FACTORY));
    while (GPIO_INPUT_GET(CONFIG_GPIO_PIN_FORCE_FACTORY) == CONFIG_GPIO_LEVEL_FORCE_FACTORY) {
        if ((timer % 5) == 0) {
            ESP_LOGE(TAG, "Force Factory boot Pin is Active!");
        }
        ets_delay_us(100000); // wait 100 ms
        timer++;
        if (timer == 30) {
            ESP_LOGE(TAG, "Forcing boot to Factory partition");
            return 1;
        }
    }
    ESP_LOGW(TAG, "Normal boot");
    #endif
    return 0;
}

/* Return the index of the selected boot partition.

   This is the preferred boot partition, as determined by the partition table &
   any OTA sequence number found in OTA data.

   This partition will only be booted if it contains a valid app image, otherwise load_boot_image() will search
   for a valid partition using this selection as the starting point.
*/
static int get_selected_boot_partition(const bootloader_state_t *bs)
{
    esp_ota_select_entry_t sa,sb;
    const esp_ota_select_entry_t *ota_select_map;

    if (bs->ota_info.offset != 0 && !ForceFactoryBoot()) { // LoBo
        // partition table has OTA data partition
GPIO_PIN_FORCE_FACTORY & GPIO_LEVEL_FORCE_FACTORY are defined in application Kconfig.projbuild:

Code: Select all

    config GPIO_PIN_FORCE_FACTORY
        int "GPIO to force boot from Factory partition"
    	depends on GPIO_INPUT_FORCE_FACTORY
        range 0 39
        default 0
        help
        Set GPIO pin to be used to force boot from Factory partition

    config GPIO_LEVEL_FORCE_FACTORY
    	depends on GPIO_INPUT_FORCE_FACTORY
        int "GPIO level to force boot from Factory partition"
        range 0 1
        default 0
        help
        Set GPIO pin level to force boot from Factory partition
It is tested and works without problem.

Similar code can be used to set the LED to some level on bootloader start:

Code: Select all

/**
 *  @function :     bootloader_main
 *  @description:   entry function of 2nd bootloader
 *
 *  @inputs:        void
 */

void bootloader_main()
{
    vddsdio_configure();
    flash_gpio_configure();
    bootloader_clock_configure();
    uart_console_configure();
    wdt_reset_check();

    #if CONFIG_BOOT_SET_LED >= 0
    gpio_pad_select_gpio(CONFIG_BOOT_SET_LED);
    if (CONFIG_BOOT_SET_LED < 32) gpio_output_set(CONFIG_BOOT_LED_ON << CONFIG_BOOT_SET_LED, (CONFIG_BOOT_LED_ON ? 0 : 1) << CONFIG_BOOT_SET_LED, 1<<CONFIG_BOOT_SET_LED,0);
    else gpio_output_set_high(CONFIG_BOOT_LED_ON << (CONFIG_BOOT_SET_LED-32), (CONFIG_BOOT_LED_ON ? 0 : 1) << (CONFIG_BOOT_SET_LED-32), 1<<(CONFIG_BOOT_SET_LED-32),0);
    ESP_LOGI(TAG, "BOOT LED set to %d", CONFIG_BOOT_LED_ON);
    #endif
In Kconfig.projbuild:

Code: Select all

    config BOOT_SET_LED
        int "Activate LED (gpio) on boot"
        range -1 33
        default -1
        help
        Set to GPIO pin to use as LED indication during boot
        not used if set to -1

    config BOOT_LED_ON
    	depends on BOOT_SET_LED >= 0
        int "Set boot LED On level"
        range 0 1
        default 0
        help
        Set to GPIO pin level for boot LED On state

jasper.z
Posts: 4
Joined: Tue Mar 27, 2018 2:13 am

Re: Customize boot mode

Postby jasper.z » Wed Mar 28, 2018 3:53 am

Thank u so much for these detailed solution on bootloader. Meanwhile, the further question is how to customize partition table which define two partition in app type simultaneously. It's required that one is factory app,the other is test app. What's we final expected is to jump into factory app or test app depends on GPIO status on bootloader.
The sample table is looks like below:

Code: Select all

# Name,   Type, SubType, Offset,   Size
nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
factory,  app,  factory, 0x10000,  512K
[color=#FF0000]test, app, test, 0x90000, 512K[/color]
ota_0,    app,  ota_0,   ,         1M
ota_1,    app,  ota_1,   ,         1M
On the other hand, I just saw below section indicates it is not supported on ESP-IDF Programming Guide":
"test (0x2) is a reserved subtype for factory test procedures. It is not currently supported by the esp-idf bootloader."
http://esp-idf.readthedocs.io/en/latest ... l#overview

chegewara
Posts: 2361
Joined: Wed Jun 14, 2017 9:00 pm

Re: Customize boot mode

Postby chegewara » Wed Mar 28, 2018 3:45 pm

Why you just dont make it another OTA partition?

Who is online

Users browsing this forum: Google [Bot] and 95 guests