diff options
Diffstat (limited to 'tools/nugget_tools.cc')
-rw-r--r-- | tools/nugget_tools.cc | 156 |
1 files changed, 55 insertions, 101 deletions
diff --git a/tools/nugget_tools.cc b/tools/nugget_tools.cc index 992f9c3..ace0249 100644 --- a/tools/nugget_tools.cc +++ b/tools/nugget_tools.cc @@ -4,8 +4,6 @@ #include <nos/NuggetClient.h> #include <chrono> -#include <cinttypes> -#include <cstring> #include <iostream> #include <thread> #include <vector> @@ -27,10 +25,19 @@ using std::chrono::duration; using std::chrono::duration_cast; using std::chrono::high_resolution_clock; using std::chrono::microseconds; -using std::string; namespace nugget_tools { +namespace { + +void WaitForHardReboot() { + // POST (which takes ~50ms) runs on a hard-reboot, plus an + // additional ~30ms for RO+RW verification. + std::this_thread::sleep_for(std::chrono::milliseconds(80)); +} + +} // namesapce + std::unique_ptr<nos::NuggetClientInterface> MakeNuggetClient() { #ifdef ANDROID std::unique_ptr<nos::NuggetClientInterface> client = @@ -71,123 +78,69 @@ bool CyclesSinceBoot(nos::NuggetClientInterface *client, uint32_t *cycles) { return true; } -static void ShowStats(const char *msg, - const struct nugget_app_low_power_stats& stats) { - printf("%s\n", msg); - printf(" hard_reset_count %" PRIu64 "\n", stats.hard_reset_count); - printf(" time_since_hard_reset %" PRIu64 "\n", - stats.time_since_hard_reset); - printf(" wake_count %" PRIu64 "\n", stats.wake_count); - printf(" time_at_last_wake %" PRIu64 "\n", stats.time_at_last_wake); - printf(" time_spent_awake %" PRIu64 "\n", stats.time_spent_awake); - printf(" deep_sleep_count %" PRIu64 "\n", stats.deep_sleep_count); - printf(" time_at_last_deep_sleep %" PRIu64 "\n", - stats.time_at_last_deep_sleep); - printf(" time_spent_in_deep_sleep %" PRIu64 "\n", - stats.time_spent_in_deep_sleep); -} - -bool RebootNugget(nos::NuggetClientInterface *client) { - struct nugget_app_low_power_stats stats0; - struct nugget_app_low_power_stats stats1; - std::vector<uint8_t> buffer; +bool RebootNugget(nos::NuggetClientInterface *client, uint8_t type) { + // Capture the time here to allow for some tolerance on the reported time. + auto start = high_resolution_clock::now(); - // Grab stats before sleeping - buffer.reserve(sizeof(struct nugget_app_low_power_stats)); - if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_GET_LOW_POWER_STATS, - buffer, &buffer) != app_status::APP_SUCCESS) { - LOG(ERROR) << "CallApp(..., NUGGET_PARAM_GET_LOW_POWER_STATS, ...) failed!\n"; + // See what time Nugget OS has now + uint32_t pre_reboot; + if (!CyclesSinceBoot(client, &pre_reboot)) { return false; } - memcpy(&stats0, buffer.data(), sizeof(stats0)); - // Capture the time here to allow for some tolerance on the reported time. - auto start = high_resolution_clock::now(); - - // Tell Nugget OS to reboot - std::vector<uint8_t> ignored; - if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, ignored, + // Tell it to reboot: 0 = soft reboot, 1 = hard reboot + std::vector<uint8_t> input_buffer(1, type); + if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, input_buffer, nullptr) != app_status::APP_SUCCESS) { LOG(ERROR) << "CallApp(..., NUGGET_PARAM_REBOOT, ...) failed!\n"; return false; } - // Grab stats after sleeping - buffer.empty(); - buffer.reserve(sizeof(struct nugget_app_low_power_stats)); - if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_GET_LOW_POWER_STATS, - buffer, &buffer) != app_status::APP_SUCCESS) { - LOG(ERROR) << "CallApp(..., NUGGET_PARAM_GET_LOW_POWER_STATS, ...) failed!\n"; - return false; + if (!type) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } else { + WaitForHardReboot(); } - memcpy(&stats1, buffer.data(), sizeof(stats1)); - // Figure a max elapsed time that Nugget OS should see (our time + 5%). - auto max_usecs = - duration_cast<microseconds>(high_resolution_clock::now() - start) * - 105 / 100; - - // Verify that Citadel rebooted - if (stats1.hard_reset_count == stats0.hard_reset_count + 1 && - stats1.time_at_last_wake == 0 && - stats1.deep_sleep_count == 0 && - std::chrono::microseconds(stats1.time_since_hard_reset) < max_usecs) { - return true; - } - - LOG(ERROR) << "Citadel didn't reboot within " - << max_usecs.count() << " microseconds\n"; - ShowStats("stats before waiting", stats0); - ShowStats("stats after waiting", stats1); - - return false; -} - -bool WaitForSleep(nos::NuggetClientInterface *client, uint32_t *seconds_waited) { - struct nugget_app_low_power_stats stats0; - struct nugget_app_low_power_stats stats1; - std::vector<uint8_t> buffer; - - buffer.reserve(sizeof(struct nugget_app_low_power_stats)); - // Grab stats before sleeping - if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_GET_LOW_POWER_STATS, - buffer, &buffer) != app_status::APP_SUCCESS) { - LOG(ERROR) << "CallApp(..., NUGGET_PARAM_GET_LOW_POWER_STATS, ...) failed!\n"; + // See what time Nugget OS has after rebooting. + uint32_t post_reboot; + if (!CyclesSinceBoot(client, &post_reboot)) { return false; } - memcpy(&stats0, buffer.data(), sizeof(stats0)); - // Wait for Citadel to fall asleep - constexpr uint32_t wait_seconds = 4; - std::this_thread::sleep_for(std::chrono::seconds(wait_seconds)); + // Hard reboots reset the clock to zero, but soft reboots should keep counting + if (!type) { + // Make sure time advanced + if (post_reboot <= pre_reboot) { + LOG(ERROR) << "pre_reboot time (" << pre_reboot << ") should be less than " + << "post_reboot time (" << post_reboot << ")\n"; + return false; + } + // Change this to elapsed time, not absolute time + post_reboot -= pre_reboot; + } - // Grab stats after sleeping - buffer.empty(); - buffer.reserve(sizeof(struct nugget_app_low_power_stats)); - if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_GET_LOW_POWER_STATS, - buffer, &buffer) != app_status::APP_SUCCESS) { - LOG(ERROR) << "CallApp(..., NUGGET_PARAM_GET_LOW_POWER_STATS, ...) failed!\n"; + // Verify that the Nugget OS counter shows a reasonable value. + // Use the elapsed time +5% for the threshold. + auto threshold_microseconds = + duration_cast<microseconds>(high_resolution_clock::now() - start) * + 105 / 100; + if (std::chrono::microseconds(post_reboot) > threshold_microseconds ) { + LOG(ERROR) << "Counter is " << post_reboot + << " but is expected to be less than " + << threshold_microseconds.count() * 1.05 << "!\n"; return false; } - memcpy(&stats1, buffer.data(), sizeof(stats1)); - - // Verify that Citadel went to sleep but didn't reboot - if (stats1.hard_reset_count == stats0.hard_reset_count && - stats1.deep_sleep_count == stats0.deep_sleep_count + 1 && - stats1.wake_count == stats0.wake_count + 1 && - stats1.time_spent_in_deep_sleep > stats0.time_spent_in_deep_sleep) { - // Yep, looks good - if (seconds_waited) { - *seconds_waited = wait_seconds; - } - return true; - } - LOG(ERROR) << "Citadel didn't sleep\n"; - ShowStats("stats before waiting", stats0); - ShowStats("stats after waiting", stats1); + // Looks okay + return true; +} - return false; +uint32_t WaitForSleep() { + constexpr uint32_t wait_seconds = 5; + std::this_thread::sleep_for(std::chrono::seconds(wait_seconds)); + // TODO: Can we check it has gone to sleep? + return wait_seconds; } bool WipeUserData(nos::NuggetClientInterface *client) { @@ -198,6 +151,7 @@ bool WipeUserData(nos::NuggetClientInterface *client) { buffer, nullptr) != app_status::APP_SUCCESS) { return false; } + WaitForHardReboot(); return true; } |