10 #include "dt/dt_aon_timer.h"
11 #include "dt/dt_rv_core_ibex.h"
12 #include "dt/dt_rv_plic.h"
13 #include "dt/dt_rv_timer.h"
19 #include "sw/device/lib/runtime/irq.h"
21 #include "sw/device/lib/testing/aon_timer_testutils.h"
22 #include "sw/device/lib/testing/rand_testutils.h"
23 #include "sw/device/lib/testing/rv_plic_testutils.h"
24 #include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
25 #include "sw/device/lib/testing/test_framework/check.h"
28 OTTF_DEFINE_TEST_CONFIG();
30 static const uint32_t kPlicTarget = 0;
31 static const uint32_t kTickFreqHz = 1000 * 1000;
32 static dif_rv_core_ibex_t rv_core_ibex;
33 static dt_rv_core_ibex_t kRvCoreIbexDt = kDtRvCoreIbex;
34 static dif_aon_timer_t aon_timer;
35 static dt_aon_timer_t kAonTimerDt = kDtAonTimerAon;
36 static dif_rv_timer_t rv_timer;
37 static dt_rv_timer_t kRvTimerDt = kDtRvTimer;
38 static dif_rv_plic_t plic;
39 static dt_rv_plic_t kRvPlicDt = kDtRvPlic;
41 static volatile dt_aon_timer_irq_t irq;
42 static volatile uint64_t irq_tick;
61 static_assert(configUSE_PREEMPTION == 0,
62 "rv_timer may be initialized already by FreeRtos");
64 static void tick_init(
void) {
65 CHECK_DIF_OK(dif_rv_timer_init_from_dt(kRvTimerDt, &rv_timer));
72 kTickFreqHz, &tick_params));
86 static uint64_t tick_count_get(
void) {
95 static void execute_test(dif_aon_timer_t *aon_timer, uint64_t irq_time_us,
96 dt_aon_timer_irq_t expected_irq) {
98 uint64_t variation =
udiv64_slow(irq_time_us * 5, 100, NULL);
100 uint64_t sleep_range_h = irq_time_us + variation;
101 uint64_t sleep_range_l = irq_time_us - variation;
106 uint64_t count_cycles = 0;
107 CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_64_from_us(irq_time_us,
109 LOG_INFO(
"Setting interrupt for %u us (%u cycles)", (uint32_t)irq_time_us,
110 (uint32_t)count_cycles);
118 irq = kDtAonTimerIrqCount;
119 if (expected_irq == kDtAonTimerIrqWkupTimerExpired) {
121 CHECK_STATUS_OK(aon_timer_testutils_wakeup_config(aon_timer, count_cycles));
124 CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(
126 (uint32_t)count_cycles,
127 (uint32_t)count_cycles * 4,
131 uint32_t start_tick = (uint32_t)tick_count_get();
133 ATOMIC_WAIT_FOR_INTERRUPT(irq != kDtAonTimerIrqCount);
135 uint32_t time_elapsed = (uint32_t)irq_tick - start_tick;
136 CHECK(time_elapsed <= sleep_range_h && time_elapsed >= sleep_range_l,
137 "Timer took %u usec which is not in the range %u usec and %u usec",
138 (uint32_t)time_elapsed, (uint32_t)sleep_range_l,
139 (uint32_t)sleep_range_h);
141 CHECK(irq == expected_irq,
"Interrupt type incorrect: exp = %d, obs = %d",
142 kDtAonTimerIrqWkupTimerExpired, irq);
144 LOG_INFO(
"Test completed in %u us", (uint32_t)irq_time_us);
150 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
152 if (devid != dt_aon_timer_instance_id(kAonTimerDt)) {
156 irq_tick = tick_count_get();
158 irq = dt_aon_timer_irq_from_plic_id(kAonTimerDt, irq_id);
160 if (irq == kDtAonTimerIrqWkupTimerExpired) {
162 }
else if (irq == kDtAonTimerIrqWdogTimerBark) {
166 CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
175 void ottf_external_nmi_handler(
void) {
180 CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
181 &aon_timer, kDtAonTimerIrqWdogTimerBark, &is_pending));
186 dif_aon_timer_irq_acknowledge(&aon_timer, kDtAonTimerIrqWdogTimerBark));
188 CHECK_DIF_OK(dif_rv_core_ibex_clear_nmi_state(&rv_core_ibex,
189 kDifRvCoreIbexNmiSourceAll));
194 irq_global_ctrl(
true);
195 irq_external_ctrl(
true);
201 CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
203 CHECK_DIF_OK(dif_rv_core_ibex_init_from_dt(kRvCoreIbexDt, &rv_core_ibex));
206 CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
209 rv_plic_testutils_irq_range_enable(
211 dt_aon_timer_irq_to_plic_id(kAonTimerDt, kDtAonTimerIrqWkupTimerExpired),
212 dt_aon_timer_irq_to_plic_id(kAonTimerDt, kDtAonTimerIrqWdogTimerBark));
222 kMinCycles = 30 * 1000,
223 kMaxCycles = 45 * 1000,
225 uint64_t low_time_range =
227 uint64_t high_time_range =
231 uint64_t irq_time = rand_testutils_gen32_range((uint32_t)low_time_range,
232 (uint32_t)high_time_range);
233 execute_test(&aon_timer, irq_time,
234 kDtAonTimerIrqWkupTimerExpired);
236 irq_time = rand_testutils_gen32_range((uint32_t)low_time_range,
237 (uint32_t)high_time_range);
238 execute_test(&aon_timer, irq_time,
239 kDtAonTimerIrqWdogTimerBark);