Software APIs
plic_sw_irq_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 "dt/dt_api.h" // Generated
6 #include "dt/dt_rv_plic.h" // Generated
10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 #include "sw/device/lib/testing/test_framework/status.h"
15 
16 #include "rv_plic_regs.h" // Generated.
17 
18 OTTF_DEFINE_TEST_CONFIG();
19 
20 static const dif_rv_plic_target_t kPlicTarget = 0;
21 
22 static dif_rv_plic_t plic0;
23 
24 static uint32_t external_intr_triggered = 0;
25 static uint32_t software_intr_triggered = 0;
26 
27 /**
28  * Configures all interrupts in PLIC.
29  */
30 static void plic_configure_irqs(dif_rv_plic_t *plic) {
31  // Set IRQ priorities to MAX and Enable the IRQ
32  for (int i = 0; i < RV_PLIC_PARAM_NUM_SRC; ++i) {
34  CHECK_DIF_OK(
36  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(plic, irq_id, kPlicTarget,
38  }
39 
40  // Set Ibex IRQ priority threshold level
41  CHECK_DIF_OK(dif_rv_plic_target_set_threshold(plic, kPlicTarget,
43 }
44 
45 /**
46  * External ISR.
47  *
48  * PLIC interrupt triggers ottf_external_isr() function. The expectation is
49  * MSIP triggers this. Inside the routine, it reads all Interrupt Pending bits
50  * and confirms only MSIP occurs.
51  */
52 void ottf_external_isr(uint32_t *exc_info) {
53  dif_rv_plic_irq_id_t interrupt_id;
54 
55  ++external_intr_triggered;
56  LOG_FATAL("External Interrupt should not occur");
57  test_status_set(kTestStatusFailed);
58 
59  // Clean up external ISRs (claim & complete)
60  CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic0, kPlicTarget, &interrupt_id));
61  CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic0, kPlicTarget, interrupt_id));
62 }
63 
64 /**
65  * Software ISR
66  *
67  * Only SW ISR should occur in this test.
68  */
69 void ottf_software_isr(uint32_t *exc_info) {
70  LOG_INFO("SOFTWARE ISR entered");
71  ++software_intr_triggered;
72 
73  // Clean up software ISRs (claim? clear?)
74  CHECK_DIF_OK(dif_rv_plic_software_irq_acknowledge(&plic0, kPlicTarget));
75 
76  LOG_INFO("Software ISR event is cleared");
77 }
78 
79 static void execute_test(dif_rv_plic_t *plic) {
80  // Force SW IRQ
81  CHECK_DIF_OK(dif_rv_plic_software_irq_force(plic, kPlicTarget));
82 
83  // Wait SW IRQ being processed
84  while (abs_mmio_read32((uint32_t)&software_intr_triggered) == 0) {
85  busy_spin_micros(10);
86  }
87 }
88 
89 bool test_main(void) {
90  // Enable IRQs on Ibex
91  irq_global_ctrl(true);
92  irq_external_ctrl(true);
93 
94  static_assert(kDtRvPlicCount >= 1, "This test requires an RV PLIC.");
95  CHECK_DIF_OK(dif_rv_plic_init_from_dt((dt_rv_plic_t)0, &plic0));
96 
97  plic_configure_irqs(&plic0);
98 
99  // Enable MSIE
100  irq_software_ctrl(true);
101 
102  execute_test(&plic0);
103 
104  // Pass condition
105  if ((abs_mmio_read32((uint32_t)&software_intr_triggered) == 1) &&
106  (abs_mmio_read32((uint32_t)&external_intr_triggered) == 0)) {
107  return true;
108  }
109 
110  return false;
111 }