mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-13 06:57:07 +03:00
Start of 5.X work
This commit is contained in:
143
components/tools/bootstate.cpp
Normal file
143
components/tools/bootstate.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "bootstate.h"
|
||||
#include "Config.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "messaging.h"
|
||||
#include "tools.h"
|
||||
static const char* TAG = "bootstate";
|
||||
|
||||
RTC_NOINIT_ATTR uint32_t RebootCounter;
|
||||
RTC_NOINIT_ATTR uint32_t RecoveryRebootCounter;
|
||||
RTC_NOINIT_ATTR uint16_t ColdBootIndicatorFlag;
|
||||
EXT_RAM_ATTR bool is_recovery_running = false;
|
||||
EXT_RAM_ATTR bool cold_boot = true;
|
||||
EXT_RAM_ATTR esp_reset_reason_t xReason = ESP_RST_UNKNOWN;
|
||||
EXT_RAM_ATTR static bool restarting = false;
|
||||
|
||||
uint32_t bootstate_read_counter(void) { return RebootCounter; }
|
||||
uint32_t bootstate_uptate_counter(int32_t xValue) {
|
||||
if (RebootCounter > 100) {
|
||||
RebootCounter = 0;
|
||||
RecoveryRebootCounter = 0;
|
||||
}
|
||||
RebootCounter = (xValue != 0) ? (RebootCounter + xValue) : 0;
|
||||
RecoveryRebootCounter = (xValue != 0) && is_recovery_running ? (RecoveryRebootCounter + xValue) : 0;
|
||||
return RebootCounter;
|
||||
}
|
||||
|
||||
void bootstate_handle_boot() {
|
||||
if (ColdBootIndicatorFlag != 0xFACE) {
|
||||
ESP_LOGI(TAG, "System is booting from power on.");
|
||||
cold_boot = true;
|
||||
ColdBootIndicatorFlag = 0xFACE;
|
||||
} else {
|
||||
cold_boot = false;
|
||||
}
|
||||
const esp_partition_t* running = esp_ota_get_running_partition();
|
||||
|
||||
xReason = esp_reset_reason();
|
||||
ESP_LOGI(TAG, "Reset reason is: %u. Running from partition %s type %s ", xReason, running->label,
|
||||
running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY ? "Factory" : "Application");
|
||||
is_recovery_running = (running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY);
|
||||
|
||||
if (!is_recovery_running) {
|
||||
/* unscheduled restart (HW, Watchdog or similar) thus increment dynamic
|
||||
* counter then log current boot statistics as a warning */
|
||||
uint32_t Counter = bootstate_uptate_counter(1); // increment counter
|
||||
ESP_LOGI(TAG, "Reboot counter=%u\n", Counter);
|
||||
if (Counter == 5) {
|
||||
guided_factory();
|
||||
}
|
||||
} else {
|
||||
uint32_t Counter = bootstate_uptate_counter(1); // increment counter
|
||||
if (RecoveryRebootCounter == 1 && Counter >= 5) {
|
||||
// First time we are rebooting in recovery after crashing
|
||||
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM,
|
||||
"System was forced into recovery mode after crash likely caused by some bad "
|
||||
"configuration\n");
|
||||
}
|
||||
ESP_LOGI(TAG, "Recovery Reboot counter=%u\n", Counter);
|
||||
if (RecoveryRebootCounter == 5) {
|
||||
ESP_LOGW(TAG, "System rebooted too many times. This could be an indication that "
|
||||
"configuration is corrupted. Erasing config.");
|
||||
if (config_erase_config()) {
|
||||
config_raise_changed(true);
|
||||
guided_factory();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Error erasing configuration");
|
||||
}
|
||||
}
|
||||
if (RecoveryRebootCounter > 5) {
|
||||
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM,
|
||||
"System was forced into recovery mode after crash likely caused by some bad "
|
||||
"configuration. Configuration was reset to factory.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) {
|
||||
if (is_recovery_running) {
|
||||
if (partition_subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
|
||||
simple_restart();
|
||||
}
|
||||
} else {
|
||||
if (partition_subtype != ESP_PARTITION_SUBTYPE_APP_FACTORY) {
|
||||
simple_restart();
|
||||
}
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
const esp_partition_t* partition;
|
||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL);
|
||||
|
||||
if (it == NULL) {
|
||||
log_send_messaging(MESSAGING_ERROR, "Reboot failed. Partitions error");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Found partition. Getting info.");
|
||||
partition = (esp_partition_t*)esp_partition_get(it);
|
||||
ESP_LOGD(TAG, "Releasing partition iterator");
|
||||
esp_partition_iterator_release(it);
|
||||
if (partition != NULL) {
|
||||
log_send_messaging(MESSAGING_INFO, "Rebooting to %s", partition->label);
|
||||
err = esp_ota_set_boot_partition(partition);
|
||||
if (err != ESP_OK) {
|
||||
log_send_messaging(MESSAGING_ERROR, "Unable to select partition for reboot: %s", esp_err_to_name(err));
|
||||
}
|
||||
} else {
|
||||
log_send_messaging(MESSAGING_ERROR, "partition type %u not found! Unable to reboot to recovery.", partition_subtype);
|
||||
}
|
||||
ESP_LOGD(TAG, "Yielding to other processes");
|
||||
taskYIELD();
|
||||
simple_restart();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t guided_restart_ota() {
|
||||
log_send_messaging(MESSAGING_WARNING, "Booting to Squeezelite");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
|
||||
return ESP_FAIL; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
esp_err_t guided_factory() {
|
||||
log_send_messaging(MESSAGING_WARNING, "Booting to recovery");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
|
||||
return ESP_FAIL; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
void simple_restart() {
|
||||
restarting = true;
|
||||
log_send_messaging(MESSAGING_WARNING, "Rebooting.");
|
||||
|
||||
TimerHandle_t timer = xTimerCreate("reboot", 1, pdFALSE, nullptr, [](TimerHandle_t xTimer) {
|
||||
if (!config_waitcommit()) {
|
||||
log_send_messaging(MESSAGING_WARNING, "Waiting for configuration to commit ");
|
||||
ESP_LOGD(TAG,"Queuing restart asynchronously to ensure all events are flushed.");
|
||||
network_async_reboot(RESTART);
|
||||
return;
|
||||
}
|
||||
vTaskDelay(750 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
xTimerDelete(xTimer, portMAX_DELAY);
|
||||
});
|
||||
xTimerStart(timer, portMAX_DELAY);
|
||||
}
|
||||
bool is_restarting() { return restarting; }
|
||||
Reference in New Issue
Block a user