Bootloader: Selecting app based on GPIO input

Hrox2504
Posts: 4
Joined: Thu Apr 11, 2024 7:02 am

Bootloader: Selecting app based on GPIO input

Postby Hrox2504 » Thu Apr 11, 2024 8:00 am

Hi everyone!

I am currently trying to tackle the following problem: I have two apps installed on my ESP32, e.g., on the factory and ota_0 partitions, and I want to select the app to boot based on the state of some given GPIO pin. I have searched the documentation for options and found the following: Apparently one could install one app in a 'test' partition and then there is some mechanism by which the test partition is booted if some GPIO is set. However, documentation on that is sparse and I did not really understand it. Do I need to overwrite the second stage bootloader (at 0x001000 I think?) to achieve the desired behaviour?

Alternatively, the following would work too: Always boot the factory app and then this app decided on whether to boot the ota_0 app based on the state of a GPIO pin. I did not find anything regard booting one app out of the other, however.

It is very important that the ota_0 app is completely agnostic to this whole process, i.e., that this would work with any binary installed in the ota_0 partition.

This problem feels like a standard problem to me, but I could not find much on the internet. I am still new to the ESP-IDF and I might just be lacking some keyword to look for. Any help is greatly appreciated!

Best,
Hrox

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: Bootloader: Selecting app based on GPIO input

Postby boarchuz » Thu Apr 11, 2024 1:01 pm

Now that we have bootloader_components, I think you could wrap bootloader_utility_get_selected_boot_partition for a fairly simple and clean solution. eg. (untested):

project_dir/bootloader_components/bootloader_select/bootloader_select.c:

Code: Select all

#include "soc/gpio_periph.h"
#include "soc/gpio_struct.h"
#include "soc/io_mux_reg.h"
#include "hal/gpio_ll.h"
#include "esp_rom_gpio.h"
#include "bootloader_common.h"
#include "bootloader_config.h"

#define BOOTLOADER_SELECT_GPIO 25

int __real_bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs);

static bool bootloader_select_is_button_pushed(void)
{
    esp_rom_gpio_pad_pullup_only(BOOTLOADER_SELECT_GPIO);
    esp_rom_gpio_pad_select_gpio(BOOTLOADER_SELECT_GPIO);
    PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[BOOTLOADER_SELECT_GPIO]);
    return (gpio_ll_get_level(&GPIO, BOOTLOADER_SELECT_GPIO) == 0);
}

int __wrap_bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
{
    if(bootloader_common_get_reset_reason(0) != DEEPSLEEP_RESET)
    {
        if(bootloader_select_is_button_pushed())
        {
            return FACTORY_INDEX;
        }
    }
    return __real_bootloader_utility_get_selected_boot_partition(bs);
}

void __attribute__((section("/DISCARD/"))) bootloader_select_include() {}

project_dir/bootloader_components/bootloader_select/CMakeLists.txt:

Code: Select all

idf_component_register(
    SRCS "bootloader_select.c"
    REQUIRES hal bootloader_support
)

idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=bootloader_utility_get_selected_boot_partition" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--require-defined=__wrap_bootloader_utility_get_selected_boot_partition" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--require-defined=bootloader_select_include" APPEND)

Hrox2504
Posts: 4
Joined: Thu Apr 11, 2024 7:02 am

Re: Bootloader: Selecting app based on GPIO input

Postby Hrox2504 » Thu Apr 11, 2024 2:02 pm

Thank you for the fast answer! I have to admit, I do not have much experience with the esp-idf/components lib, since I have been mostly using the Arduino framework together with PlatformIO. Is there any documentation available regarding the functions and macros you have used in the example code or will I just have to read the headers and source code? Thanks in advance :)

Who is online

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