Software APIs
aon_timer_sleep_wdog_sleep_pause_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 
14 #include "sw/device/lib/testing/aon_timer_testutils.h"
15 #include "sw/device/lib/testing/pwrmgr_testutils.h"
16 #include "sw/device/lib/testing/rstmgr_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 
20 static const dt_pwrmgr_t kPwrmgrDt = 0;
21 static_assert(kDtPwrmgrCount == 1, "this library expects exactly one pwrmgr");
22 static const dt_rstmgr_t kRstmgrDt = 0;
23 static_assert(kDtRstmgrCount == 1, "this library expects exactly one rstmgr");
24 static const dt_aon_timer_t kAonTimerDt = 0;
25 static_assert(kDtAonTimerCount == 1,
26  "this library expects exactly one aon_timer");
27 
28 #define IDLE_TIME_US 10
29 #define WKUP_TIME_US 2000
30 OTTF_DEFINE_TEST_CONFIG();
31 
32 bool test_main(void) {
33  // Initialize pwrmgr.
34  dif_pwrmgr_t pwrmgr;
35  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
36 
37  // Initialize rstmgr to check the reset reason.
38  dif_rstmgr_t rstmgr;
39  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
40 
41  // Initialize aon timer to use the wdog.
42  dif_aon_timer_t aon_timer;
43  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
44 
45  // Find wakeup and reset sources.
46  dif_pwrmgr_request_sources_t wakeup_sources;
47  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
48  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
49  kDtAonTimerWakeupWkupReq, &wakeup_sources));
50  dif_pwrmgr_request_sources_t reset_sources;
51  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
52  &pwrmgr, kDifPwrmgrReqTypeReset, dt_aon_timer_instance_id(kAonTimerDt),
53  kDtAonTimerResetReqAonTimer, &reset_sources));
54 
55  // Enable aon_timer watchdog reset.
56  // Set wdog as a reset source.
57  CHECK_DIF_OK(dif_pwrmgr_set_request_sources(
58  &pwrmgr, kDifPwrmgrReqTypeReset, reset_sources, kDifToggleEnabled));
59 
60  // Check if there was a HW reset caused by the wdog bite.
61  dif_rstmgr_reset_info_bitfield_t rst_info = rstmgr_testutils_reason_get();
62  rstmgr_testutils_reason_clear();
63 
64  uint64_t wkup_cnt;
65  uint32_t wdog_cnt;
66  if (rst_info == kDifRstmgrResetInfoPor) {
67  LOG_INFO("Booting for the first time, setting wdog");
68 
69  // Configure watchdog sooner then wakeup, but with pause enabled.
70  uint64_t wkup_cycles = 0;
71  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_64_from_us(
72  WKUP_TIME_US, &wkup_cycles));
73 
74  // The actual expiration of the watchdog is unimportant, as the test
75  // mainly checks the count.
76  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(&aon_timer, UINT32_MAX,
77  UINT32_MAX, true));
78  CHECK_STATUS_OK(aon_timer_testutils_wakeup_config(&aon_timer, wkup_cycles));
79 
80  busy_spin_micros(IDLE_TIME_US);
81 
82  // Since watchdog was started first, its count should be larger.
83  CHECK_DIF_OK(dif_aon_timer_watchdog_get_count(&aon_timer, &wdog_cnt));
84  CHECK_DIF_OK(dif_aon_timer_wakeup_get_count(&aon_timer, &wkup_cnt));
85  CHECK(wdog_cnt >= wkup_cnt);
86 
87  // Deep sleep.
88  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources,
89  /*domain_config=*/0));
90 
91  // Enter low power mode.
92  LOG_INFO("Issue WFI to enter sleep");
94  } else if (rst_info == kDifRstmgrResetInfoLowPowerExit) {
95  LOG_INFO("Booting for the second time due to wakeup");
96  // Since watchdog count was paused during low power, wakeup
97  // count should now be larger.
98  CHECK_DIF_OK(dif_aon_timer_wakeup_get_count(&aon_timer, &wkup_cnt));
99  CHECK_DIF_OK(dif_aon_timer_watchdog_get_count(&aon_timer, &wdog_cnt));
100  CHECK(wdog_cnt < wkup_cnt);
101 
102  } else {
103  LOG_ERROR("Got unexpected reset_info=0x%x", rst_info);
104  }
105 
106  return true;
107 }