forked from espressif/esp-idf
Merge branch 'feature/bootloader_pin_level_pr7089' into 'master'
bootloader: Add configurable pin level for factory reset (PR) Closes IDFGH-5337 See merge request espressif/esp-idf!13956
This commit is contained in:
@@ -441,7 +441,7 @@ UT_001:
|
|||||||
|
|
||||||
UT_002:
|
UT_002:
|
||||||
extends: .unit_test_esp32_template
|
extends: .unit_test_esp32_template
|
||||||
parallel: 15
|
parallel: 16
|
||||||
tags:
|
tags:
|
||||||
- ESP32_IDF
|
- ESP32_IDF
|
||||||
- UT_T1_1
|
- UT_T1_1
|
||||||
|
@@ -117,8 +117,8 @@ menu "Bootloader config"
|
|||||||
Allows to reset the device to factory settings:
|
Allows to reset the device to factory settings:
|
||||||
- clear one or more data partitions;
|
- clear one or more data partitions;
|
||||||
- boot from "factory" partition.
|
- boot from "factory" partition.
|
||||||
The factory reset will occur if there is a GPIO input pulled low while device starts up.
|
The factory reset will occur if there is a GPIO input held at the configured level while
|
||||||
See settings below.
|
device starts up. See settings below.
|
||||||
|
|
||||||
config BOOTLOADER_NUM_PIN_FACTORY_RESET
|
config BOOTLOADER_NUM_PIN_FACTORY_RESET
|
||||||
int "Number of the GPIO input for factory reset"
|
int "Number of the GPIO input for factory reset"
|
||||||
@@ -127,9 +127,23 @@ menu "Bootloader config"
|
|||||||
range 0 44 if IDF_TARGET_ESP32S2
|
range 0 44 if IDF_TARGET_ESP32S2
|
||||||
default 4
|
default 4
|
||||||
help
|
help
|
||||||
The selected GPIO will be configured as an input with internal pull-up enabled.
|
The selected GPIO will be configured as an input with internal pull-up enabled (note that on some SoCs.
|
||||||
To trigger a factory reset, this GPIO must be pulled low on reset.
|
not all pins have an internal pull-up, consult the hardware datasheet for details.) To trigger a factory
|
||||||
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
|
reset, this GPIO must be held high or low (as configured) on startup.
|
||||||
|
|
||||||
|
choice BOOTLOADER_FACTORY_RESET_PIN_LEVEL
|
||||||
|
bool "Factory reset GPIO level"
|
||||||
|
depends on BOOTLOADER_FACTORY_RESET
|
||||||
|
default BOOTLOADER_FACTORY_RESET_PIN_LOW
|
||||||
|
help
|
||||||
|
Pin level for factory reset, can be triggered on low or high.
|
||||||
|
|
||||||
|
config BOOTLOADER_FACTORY_RESET_PIN_LOW
|
||||||
|
bool "Reset on GPIO low"
|
||||||
|
|
||||||
|
config BOOTLOADER_FACTORY_RESET_PIN_HIGH
|
||||||
|
bool "Reset on GPIO high"
|
||||||
|
endchoice
|
||||||
|
|
||||||
config BOOTLOADER_OTA_DATA_ERASE
|
config BOOTLOADER_OTA_DATA_ERASE
|
||||||
bool "Clear OTA data on factory reset (select factory partition)"
|
bool "Clear OTA data on factory reset (select factory partition)"
|
||||||
|
@@ -90,7 +90,11 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
|||||||
if (bootloader_common_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
if (bootloader_common_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
||||||
// Factory firmware.
|
// Factory firmware.
|
||||||
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
||||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
bool reset_level = false;
|
||||||
|
#if CONFIG_BOOTLOADER_FACTORY_RESET_PIN_HIGH
|
||||||
|
reset_level = true;
|
||||||
|
#endif
|
||||||
|
if (bootloader_common_check_long_hold_gpio_level(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO, reset_level) == GPIO_LONG_HOLD) {
|
||||||
ESP_LOGI(TAG, "Detect a condition of the factory reset");
|
ESP_LOGI(TAG, "Detect a condition of the factory reset");
|
||||||
bool ota_data_erase = false;
|
bool ota_data_erase = false;
|
||||||
#ifdef CONFIG_BOOTLOADER_OTA_DATA_ERASE
|
#ifdef CONFIG_BOOTLOADER_OTA_DATA_ERASE
|
||||||
|
@@ -62,18 +62,37 @@ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s);
|
|||||||
bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s);
|
bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the GPIO input is a long hold or a short hold.
|
* @brief Check if a GPIO input is held low for a long period, short period, or not
|
||||||
|
* at all.
|
||||||
|
*
|
||||||
|
* This function will configure the specified GPIO as an input with internal pull-up enabled.
|
||||||
*
|
*
|
||||||
* Number of the GPIO input will be configured as an input with internal pull-up enabled.
|
|
||||||
* If the GPIO input is held low continuously for delay_sec period then it is a long hold.
|
* If the GPIO input is held low continuously for delay_sec period then it is a long hold.
|
||||||
* If the GPIO input is held low for less period then it is a short hold.
|
* If the GPIO input is held low for less period then it is a short hold.
|
||||||
*
|
*
|
||||||
* @param[in] num_pin Number of the GPIO input.
|
* @param[in] num_pin Number of the GPIO input.
|
||||||
* @param[in] delay_sec Input must be driven low for at least this long, continuously.
|
* @param[in] delay_sec Input must be driven low for at least this long, continuously.
|
||||||
* @return esp_comm_gpio_hold_t Defines type of hold a GPIO in low state.
|
* @return esp_comm_gpio_hold_t Type of low level hold detected, if any.
|
||||||
*/
|
*/
|
||||||
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec);
|
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a GPIO input is held low or high for a long period, short period, or not
|
||||||
|
* at all.
|
||||||
|
*
|
||||||
|
* This function will configure the specified GPIO as an input with internal pull-up enabled.
|
||||||
|
*
|
||||||
|
* If the GPIO input is held at 'level' continuously for delay_sec period then it is a long hold.
|
||||||
|
* If the GPIO input is held at 'level' for less period then it is a short hold.
|
||||||
|
*
|
||||||
|
* @param[in] num_pin Number of the GPIO input.
|
||||||
|
* @param[in] delay_sec Input must be driven to 'level' for at least this long, continuously.
|
||||||
|
* @param[in] level Input pin level to trigger on hold
|
||||||
|
* @return esp_comm_gpio_hold_t Type of hold detected, if any.
|
||||||
|
*/
|
||||||
|
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio_level(uint32_t num_pin, uint32_t delay_sec, bool level);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Erase the partition data that is specified in the transferred list.
|
* @brief Erase the partition data that is specified in the transferred list.
|
||||||
*
|
*
|
||||||
|
@@ -40,6 +40,11 @@
|
|||||||
static const char* TAG = "boot_comm";
|
static const char* TAG = "boot_comm";
|
||||||
|
|
||||||
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec)
|
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec)
|
||||||
|
{
|
||||||
|
return bootloader_common_check_long_hold_gpio_level(num_pin, delay_sec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio_level(uint32_t num_pin, uint32_t delay_sec, bool level)
|
||||||
{
|
{
|
||||||
esp_rom_gpio_pad_select_gpio(num_pin);
|
esp_rom_gpio_pad_select_gpio(num_pin);
|
||||||
if (GPIO_PIN_MUX_REG[num_pin]) {
|
if (GPIO_PIN_MUX_REG[num_pin]) {
|
||||||
@@ -47,11 +52,11 @@ esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, ui
|
|||||||
}
|
}
|
||||||
esp_rom_gpio_pad_pullup_only(num_pin);
|
esp_rom_gpio_pad_pullup_only(num_pin);
|
||||||
uint32_t tm_start = esp_log_early_timestamp();
|
uint32_t tm_start = esp_log_early_timestamp();
|
||||||
if (gpio_ll_get_level(&GPIO, num_pin) == 1) {
|
if (gpio_ll_get_level(&GPIO, num_pin) != level) {
|
||||||
return GPIO_NOT_HOLD;
|
return GPIO_NOT_HOLD;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if (gpio_ll_get_level(&GPIO, num_pin) != 0) {
|
if (gpio_ll_get_level(&GPIO, num_pin) != level) {
|
||||||
return GPIO_SHORT_HOLD;
|
return GPIO_SHORT_HOLD;
|
||||||
}
|
}
|
||||||
} while (delay_sec > ((esp_log_early_timestamp() - tm_start) / 1000L));
|
} while (delay_sec > ((esp_log_early_timestamp() - tm_start) / 1000L));
|
||||||
|
@@ -70,9 +70,11 @@ Partitions of type "app" cannot be specified here.
|
|||||||
|
|
||||||
:ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from "factory" partition after a factory reset. The OTA data partition will be cleared.
|
:ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from "factory" partition after a factory reset. The OTA data partition will be cleared.
|
||||||
|
|
||||||
:ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- number of the GPIO input for factory reset uses to trigger a factory reset, this GPIO must be pulled low on reset to trigger this.
|
:ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- number of the GPIO input for factory reset uses to trigger a factory reset, this GPIO must be pulled low or high (configurable) on reset to trigger this.
|
||||||
|
|
||||||
:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed.
|
:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed.
|
||||||
|
|
||||||
|
:ref:`CONFIG_BOOTLOADER_FACTORY_RESET_PIN_LEVEL` - configure whether a factory reset should trigger on a high or low level of the GPIO. If the GPIO has an internal pullup then this is enabled before the pin is sampled, consult the {IDF_TARGET_NAME} datasheet for details on pin internal pullups.
|
||||||
|
|
||||||
Partition table.::
|
Partition table.::
|
||||||
|
|
||||||
|
@@ -46,9 +46,12 @@ import re
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from yaml import CLoader as Loader
|
from yaml import CLoader
|
||||||
|
has_cloader = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from yaml import Loader as Loader
|
has_cloader = False
|
||||||
|
|
||||||
|
from yaml import Loader
|
||||||
|
|
||||||
from . import CaseConfig, GitlabCIJob, SearchCases, console_log
|
from . import CaseConfig, GitlabCIJob, SearchCases, console_log
|
||||||
|
|
||||||
@@ -180,7 +183,7 @@ class AssignTest(object):
|
|||||||
def _parse_gitlab_ci_config(self, ci_config_file):
|
def _parse_gitlab_ci_config(self, ci_config_file):
|
||||||
|
|
||||||
with open(ci_config_file, 'r') as f:
|
with open(ci_config_file, 'r') as f:
|
||||||
ci_config = yaml.load(f, Loader=Loader)
|
ci_config = yaml.load(f, Loader=CLoader if has_cloader else Loader)
|
||||||
|
|
||||||
job_list = list()
|
job_list = list()
|
||||||
for job_name in ci_config:
|
for job_name in ci_config:
|
||||||
@@ -319,7 +322,7 @@ class AssignTest(object):
|
|||||||
# failures
|
# failures
|
||||||
if failed_to_assign:
|
if failed_to_assign:
|
||||||
console_log('Too many test cases vs jobs to run. '
|
console_log('Too many test cases vs jobs to run. '
|
||||||
'Please increase parallel count in tools/ci/config/target-test.yml '
|
'Please increase parallel count in .gitlab/ci/target-test.yml '
|
||||||
'for jobs with specific tags:', 'R')
|
'for jobs with specific tags:', 'R')
|
||||||
failed_group_count = self._count_groups_by_keys(failed_to_assign)
|
failed_group_count = self._count_groups_by_keys(failed_to_assign)
|
||||||
for tags in failed_group_count:
|
for tags in failed_group_count:
|
||||||
|
Reference in New Issue
Block a user