diff --git a/config-custom.cvs b/config-custom.cvs index f7aec3a62..0ad87bcab 100644 --- a/config-custom.cvs +++ b/config-custom.cvs @@ -47,5 +47,5 @@ DS4432U,data,u16,0 INA260,data,u16,0 # TPS546 (0,1) TPS546,data,u16,1 -# Self Test Power Consumption Target (> 0) +# Self-test Power Consumption Target (> 0) power_cons_tgt,data,u16,12 diff --git a/flashing.md b/flashing.md index e6c9eeda2..9941efd22 100644 --- a/flashing.md +++ b/flashing.md @@ -17,4 +17,4 @@ You can flash [factory images](https://github.com/bitaxeorg/ESP-Miner/releases) - Keep waiting until the console on ESP Tool says "Leaving..." - If you are _sure_ you have seen ESP Tool say "Leaving..." then you're bitaxe might restart. - If you bitaxe hasn't restarted, you can press the RESET button on the bitaxe -- The self test should run. this can take a second. You'll need to press the RESET button on the bitaxe once the self test has passed. +- The self-test should run. this can take a second. You'll need to press the RESET button on the bitaxe once the self-test has passed. diff --git a/main/global_state.h b/main/global_state.h index 450e471aa..098cf3f15 100644 --- a/main/global_state.h +++ b/main/global_state.h @@ -75,10 +75,11 @@ typedef struct typedef struct { - bool active; + bool is_active; + bool is_finished; char *message; - bool result; - bool finished; + char *result; + char *finished; } SelfTestModule; typedef struct diff --git a/main/nvs_config.c b/main/nvs_config.c index d5419018a..53bbaaa71 100644 --- a/main/nvs_config.c +++ b/main/nvs_config.c @@ -166,3 +166,20 @@ void nvs_config_set_u64(const char * key, const uint64_t value) } nvs_close(handle); } + +void nvs_config_commit() +{ + nvs_handle handle; + esp_err_t err; + err = nvs_open(NVS_CONFIG_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Could not open nvs"); + return; + } + + err = nvs_commit(handle); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Could not commit nvs"); + } + nvs_close(handle); +} diff --git a/main/nvs_config.h b/main/nvs_config.h index c8bf9c4b4..db8cb077b 100644 --- a/main/nvs_config.h +++ b/main/nvs_config.h @@ -65,5 +65,6 @@ int32_t nvs_config_get_i32(const char * key, const int32_t default_value); void nvs_config_set_i32(const char * key, const int32_t value); uint64_t nvs_config_get_u64(const char * key, const uint64_t default_value); void nvs_config_set_u64(const char * key, const uint64_t value); +void nvs_config_commit(void); #endif // MAIN_NVS_CONFIG_H diff --git a/main/screen.c b/main/screen.c index ca9c712b7..e8a86dd7e 100644 --- a/main/screen.c +++ b/main/screen.c @@ -96,7 +96,7 @@ static lv_obj_t * create_scr_self_test() { lv_obj_t * scr = create_flex_screen(4); lv_obj_t *label1 = lv_label_create(scr); - lv_label_set_text(label1, "BITAXE SELF TEST"); + lv_label_set_text(label1, "BITAXE SELF-TEST"); self_test_message_label = lv_label_create(scr); self_test_result_label = lv_label_create(scr); @@ -318,23 +318,17 @@ static void screen_update_cb(lv_timer_t * timer) } } - if (GLOBAL_STATE->SELF_TEST_MODULE.active) { + if (GLOBAL_STATE->SELF_TEST_MODULE.is_active) { screen_show(SCR_SELF_TEST); SelfTestModule * self_test = &GLOBAL_STATE->SELF_TEST_MODULE; lv_label_set_text(self_test_message_label, self_test->message); - if (self_test->finished && !self_test_finished) { + if (self_test->is_finished && !self_test_finished) { self_test_finished = true; - - if (self_test->result) { - lv_label_set_text(self_test_result_label, "TESTS PASS!"); - lv_label_set_text(self_test_finished_label, "Press RESET button to start Bitaxe."); - } else { - lv_label_set_text(self_test_result_label, "TESTS FAIL!"); - lv_label_set_text(self_test_finished_label, "Hold BOOT button for 2 seconds to cancel self test, or press RESET to run again."); - } + lv_label_set_text(self_test_result_label, self_test->result); + lv_label_set_text(self_test_finished_label, self_test->finished); } return; diff --git a/main/self_test/self_test.c b/main/self_test/self_test.c index 96b1d821e..49720af40 100644 --- a/main/self_test/self_test.c +++ b/main/self_test/self_test.c @@ -35,9 +35,6 @@ #define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE -#define TESTS_FAILED 0 -#define TESTS_PASSED 1 - /////Test Constants///// //Test Fan Speed #define FAN_SPEED_TARGET_MIN 1000 //RPM @@ -51,30 +48,28 @@ static const char * TAG = "self_test"; -SemaphoreHandle_t BootSemaphore; +static SemaphoreHandle_t longPressSemaphore; +static bool isFactoryTest = false; //local function prototypes static void tests_done(GlobalState * GLOBAL_STATE, bool test_result); -static bool should_test(GlobalState * GLOBAL_STATE) { - // Optionally hold the boot button - if (gpio_get_level(CONFIG_GPIO_BUTTON_BOOT) == 0) { // LOW when pressed +static bool should_test() { + uint64_t is_factory_flash = nvs_config_get_u64(NVS_CONFIG_BEST_DIFF, 0) < 1; + uint16_t is_self_test_flag_set = nvs_config_get_u16(NVS_CONFIG_SELF_TEST, 0); + if (is_factory_flash && is_self_test_flag_set) { + isFactoryTest = true; return true; } - bool is_max = GLOBAL_STATE->DEVICE_CONFIG.family.asic.id == BM1397; - uint64_t best_diff = nvs_config_get_u64(NVS_CONFIG_BEST_DIFF, 0); - uint16_t should_self_test = nvs_config_get_u16(NVS_CONFIG_SELF_TEST, 0); - if (should_self_test == 1 && !is_max && best_diff < 1) { - return true; - } - return false; + // Optionally start self-test when boot button is pressed + return gpio_get_level(CONFIG_GPIO_BUTTON_BOOT) == 0; // LOW when pressed } static void reset_self_test() { ESP_LOGI(TAG, "Long press detected..."); // Give the semaphore back - xSemaphoreGive(BootSemaphore); + xSemaphoreGive(longPressSemaphore); } static void display_msg(char * msg, GlobalState * GLOBAL_STATE) @@ -201,7 +196,7 @@ esp_err_t test_voltage_regulator(GlobalState * GLOBAL_STATE) { if (init_voltage_regulator(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "VCORE init failed!"); display_msg("VCORE:FAIL", GLOBAL_STATE); - //tests_done(GLOBAL_STATE, TESTS_FAILED); + //tests_done(GLOBAL_STATE, false); return ESP_FAIL; } @@ -210,7 +205,7 @@ esp_err_t test_voltage_regulator(GlobalState * GLOBAL_STATE) { if (DS4432U_test() != ESP_OK) { ESP_LOGE(TAG, "DS4432 test failed!"); display_msg("DS4432U:FAIL", GLOBAL_STATE); - //tests_done(GLOBAL_STATE, TESTS_FAILED); + //tests_done(GLOBAL_STATE, false); return ESP_FAIL; } } @@ -263,19 +258,23 @@ bool self_test(void * pvParameters) { GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters; - // Should we run the self test? - if (!should_test(GLOBAL_STATE)) return false; + // Should we run the self-test? + if (!should_test()) return false; - ESP_LOGI(TAG, "Running Self Tests"); + if (isFactoryTest) { + ESP_LOGI(TAG, "Running factory self-test"); + } else { + ESP_LOGI(TAG, "Running manual self-test"); + } - GLOBAL_STATE->SELF_TEST_MODULE.active = true; + GLOBAL_STATE->SELF_TEST_MODULE.is_active = true; // Create a binary semaphore - BootSemaphore = xSemaphoreCreateBinary(); + longPressSemaphore = xSemaphoreCreateBinary(); gpio_install_isr_service(0); - if (BootSemaphore == NULL) { + if (longPressSemaphore == NULL) { ESP_LOGE(TAG, "Failed to create semaphore"); return true; } @@ -283,48 +282,48 @@ bool self_test(void * pvParameters) //Run PSRAM test if(test_psram(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "NO PSRAM on device!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //Run display tests if (test_display(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Display test failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //Run input tests if (test_input(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Input test failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //Run screen tests if (test_screen(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Screen test failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //Init peripherals EMC2101 and INA260 (if present) if (test_init_peripherals(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Peripherals init failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //Voltage Regulator Testing if (test_voltage_regulator(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Voltage Regulator test failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } if (asic_reset() != ESP_OK) { ESP_LOGE(TAG, "ASIC reset failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //test for number of ASICs if (SERIAL_init() != ESP_OK) { ESP_LOGE(TAG, "SERIAL init failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY); @@ -335,11 +334,11 @@ bool self_test(void * pvParameters) ESP_LOGI(TAG, "%u chips detected, %u expected", chips_detected, chips_expected); if (chips_detected != chips_expected) { - ESP_LOGE(TAG, "SELF TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, chips_expected); + ESP_LOGE(TAG, "SELF-TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, chips_expected); char error_buf[20]; snprintf(error_buf, 20, "ASIC:FAIL %d CHIPS", chips_detected); display_msg(error_buf, GLOBAL_STATE); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //test for voltage regulator faults @@ -348,7 +347,7 @@ bool self_test(void * pvParameters) char error_buf[20]; snprintf(error_buf, 20, "VCORE:PWR FAULT"); display_msg(error_buf, GLOBAL_STATE); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } //setup and test hashrate @@ -357,7 +356,7 @@ bool self_test(void * pvParameters) if (SERIAL_set_baud(baud) != ESP_OK) { ESP_LOGE(TAG, "SERIAL set baud failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs = malloc(sizeof(bm_job *) * 128); @@ -446,14 +445,14 @@ bool self_test(void * pvParameters) if (hash_rate < expected_hashrate_mhs) { display_msg("HASHRATE:FAIL", GLOBAL_STATE); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } free(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs); free(GLOBAL_STATE->valid_jobs); if (test_core_voltage(GLOBAL_STATE) != ESP_OK) { - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } // TODO: Maybe make a test equivalent for test values @@ -461,46 +460,61 @@ bool self_test(void * pvParameters) if (test_INA260_power_consumption(GLOBAL_STATE->DEVICE_CONFIG.power_consumption_target, POWER_CONSUMPTION_MARGIN) != ESP_OK) { ESP_LOGE(TAG, "INA260 Power Draw Failed, target %.2f", (float)GLOBAL_STATE->DEVICE_CONFIG.power_consumption_target); display_msg("POWER:FAIL", GLOBAL_STATE); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } } if (GLOBAL_STATE->DEVICE_CONFIG.TPS546) { if (test_TPS546_power_consumption(GLOBAL_STATE->DEVICE_CONFIG.power_consumption_target, POWER_CONSUMPTION_MARGIN) != ESP_OK) { ESP_LOGE(TAG, "TPS546 Power Draw Failed, target %.2f", (float)GLOBAL_STATE->DEVICE_CONFIG.power_consumption_target); display_msg("POWER:FAIL", GLOBAL_STATE); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } } if (test_fan_sense(GLOBAL_STATE) != ESP_OK) { ESP_LOGE(TAG, "Fan test failed!"); - tests_done(GLOBAL_STATE, TESTS_FAILED); + tests_done(GLOBAL_STATE, false); } - tests_done(GLOBAL_STATE, TESTS_PASSED); + tests_done(GLOBAL_STATE, true); return true; } -static void tests_done(GlobalState * GLOBAL_STATE, bool test_result) +static void tests_done(GlobalState * GLOBAL_STATE, bool isTestPassed) { - GLOBAL_STATE->SELF_TEST_MODULE.result = test_result; - GLOBAL_STATE->SELF_TEST_MODULE.finished = true; VCORE_set_voltage(0.0f, GLOBAL_STATE); - if (test_result == TESTS_FAILED) { - ESP_LOGI(TAG, "SELF TESTS FAIL -- Press RESET to continue"); - while (1) { - // Wait here forever until reset_self_test() gives the BootSemaphore - if (xSemaphoreTake(BootSemaphore, portMAX_DELAY) == pdTRUE) { - nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0); - //wait 100ms for nvs write to finish? - vTaskDelay(100 / portTICK_PERIOD_MS); - esp_restart(); - } + if (isTestPassed) { + if (isFactoryTest) { + ESP_LOGI(TAG, "Self-test flag cleared"); + nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0); } + ESP_LOGI(TAG, "SELF-TEST PASS! -- Press RESET button to restart."); + GLOBAL_STATE->SELF_TEST_MODULE.result = "SELF-TEST PASS!"; + GLOBAL_STATE->SELF_TEST_MODULE.finished = "Press RESET button to restart."; } else { - nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0); - ESP_LOGI(TAG, "Self Tests Passed!!!"); + // isTestFailed + GLOBAL_STATE->SELF_TEST_MODULE.result = "SELF-TEST FAIL!"; + if (isFactoryTest) { + ESP_LOGI(TAG, "SELF-TEST FAIL! -- Hold BOOT button for 2 seconds to cancel self-test, or press RESET to run self-test again."); + GLOBAL_STATE->SELF_TEST_MODULE.finished = "Hold BOOT button for 2 seconds to cancel self-test, or press RESET to run self-test again."; + GLOBAL_STATE->SELF_TEST_MODULE.is_finished = true; + while (1) { + // Wait here forever until reset_self_test() gives the longPressSemaphore + if (xSemaphoreTake(longPressSemaphore, portMAX_DELAY) == pdTRUE) { + ESP_LOGI(TAG, "Self-test flag cleared"); + nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0); + // flush all pending NVS writes + nvs_config_commit(); + esp_restart(); + } + } + } else { + ESP_LOGI(TAG, "SELF-TEST FAIL -- Press RESET button to restart."); + GLOBAL_STATE->SELF_TEST_MODULE.finished = "Press RESET button to restart."; + } + } + GLOBAL_STATE->SELF_TEST_MODULE.is_finished = true; }