aboutsummaryrefslogtreecommitdiff
path: root/tools/nugget_tools.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nugget_tools.cc')
-rw-r--r--tools/nugget_tools.cc156
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;
}