Software APIs
aon_timer_wdog_bite_reset_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <limits.h>
6 #include <stdbool.h>
7 #include <stdint.h>
8 
15 #include "sw/device/lib/testing/aon_timer_testutils.h"
16 #include "sw/device/lib/testing/pwrmgr_testutils.h"
17 #include "sw/device/lib/testing/rstmgr_testutils.h"
18 #include "sw/device/lib/testing/test_framework/check.h"
20 
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 /**
26  * Configure the wdog.
27  */
28 static void config_wdog(const dif_aon_timer_t *aon_timer,
29  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
30  uint64_t bite_time_us) {
31  uint32_t bark_cycles = 0;
32  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bark_time_us,
33  &bark_cycles));
34  uint32_t bite_cycles = 0;
35  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bite_time_us,
36  &bite_cycles));
37 
38  LOG_INFO("Wdog will bark after %u us and bite after %u us",
39  (uint32_t)bark_time_us, (uint32_t)bite_time_us);
40 
41  // Set wdog as a reset source.
43  kDifPwrmgrResetRequestSourceTwo,
45 
46  // Setup the wdog bark and bite timeouts.
47  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(
48  aon_timer, (uint32_t)bark_cycles, (uint32_t)bite_cycles, false));
49 }
50 
51 /**
52  * Execute the aon timer wdog bite reset test.
53  */
54 static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
55  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
56  uint64_t bite_time_us = bark_time_us * 2;
57  config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
58 
59  CHECK(bark_time_us <= UINT32_MAX, "bark_time_us must fit in a uint32_t");
60 
61  // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
62  // precaution.
63  uint32_t wait_us = (uint32_t)bark_time_us +
64  (uint32_t)udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1,
65  kClockFreqAonHz, NULL);
66 
67  // Wait bark time and check that the bark interrupt requested.
68  busy_spin_micros(wait_us);
69  bool is_pending = false;
70  CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
71  aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
72  CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
73  wait_us);
74 
75  // Wait for the remaining time to the wdog bite.
76  busy_spin_micros(wait_us);
77  // If we arrive here the test must fail.
78  CHECK(false, "Timeout waiting for Wdog bite reset!");
79 }
80 
81 /**
82  * Execute the aon timer wdog bite reset during sleep test.
83  */
84 static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
85  const dif_pwrmgr_t *pwrmgr,
86  uint64_t bark_time_us) {
87  uint64_t bite_time_us = bark_time_us * 2;
88  config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
89 
90  // Program the pwrmgr to go to deep sleep state (clocks off).
91  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(
92  pwrmgr, kDifPwrmgrWakeupRequestSourceTwo, 0));
93  // Enter in low power mode.
95  // If we arrive here the test must fail.
96  CHECK(false, "Fail to enter in low power mode!");
97 }
98 
99 bool test_main(void) {
100  // Initialize pwrmgr.
101  dif_pwrmgr_t pwrmgr;
102  CHECK_DIF_OK(dif_pwrmgr_init(
104 
105  // Initialize rstmgr to check the reset reason.
106  dif_rstmgr_t rstmgr;
107  CHECK_DIF_OK(dif_rstmgr_init(
109 
110  // Initialize aon timer to use the wdog.
111  dif_aon_timer_t aon_timer;
112  CHECK_DIF_OK(dif_aon_timer_init(
114 
115  // Check if there was a HW reset caused by the wdog bite.
117  rst_info = rstmgr_testutils_reason_get();
118  rstmgr_testutils_reason_clear();
119 
120  CHECK(rst_info == kDifRstmgrResetInfoPor ||
121  rst_info == kDifRstmgrResetInfoWatchdog ||
122  rst_info ==
123  (kDifRstmgrResetInfoWatchdog | kDifRstmgrResetInfoLowPowerExit),
124  "Wrong reset reason %02X", rst_info);
125 
126  if (rst_info == kDifRstmgrResetInfoPor) {
127  LOG_INFO("Booting for the first time, setting wdog");
128  // Executing the wdog bite reset test.
129  wdog_bite_test(&aon_timer, &pwrmgr, /*bark_time_us=*/200);
130  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
131  LOG_INFO("Booting for the second time due to wdog bite reset");
132  // Executing the wdog bite reset during sleep test.
133  sleep_wdog_bite_test(&aon_timer, &pwrmgr, /*bark_time_us=*/200);
134  } else if (rst_info ==
135  (kDifRstmgrResetInfoWatchdog | kDifRstmgrResetInfoLowPowerExit)) {
136  LOG_INFO("Booting for the third time due to wdog bite reset during sleep");
137  return true;
138  }
139 
140  return false;
141 }